1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.messaging.ui;
17
18import android.content.Context;
19import android.database.Cursor;
20import android.view.LayoutInflater;
21import android.view.View;
22import android.view.ViewGroup;
23import android.widget.AbsListView;
24import android.widget.AbsListView.OnScrollListener;
25import android.widget.CursorAdapter;
26import android.widget.ListView;
27
28import com.android.messaging.util.ImeUtil;
29
30/**
31 * Produces and holds a list view and its tab header to be displayed in a ViewPager.
32 */
33public abstract class CustomHeaderPagerListViewHolder extends BasePagerViewHolder
34        implements CustomHeaderPagerViewHolder {
35    private final Context mContext;
36    private final CursorAdapter mListAdapter;
37    private boolean mListCursorInitialized;
38    private ListView mListView;
39
40    public CustomHeaderPagerListViewHolder(final Context context,
41            final CursorAdapter adapter) {
42        mContext = context;
43        mListAdapter = adapter;
44    }
45
46    @Override
47    protected View createView(ViewGroup container) {
48        final LayoutInflater inflater = (LayoutInflater)
49                mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
50        final View view = inflater.inflate(
51                getLayoutResId(),
52                null /* root */,
53                false /* attachToRoot */);
54        final ListView listView = (ListView) view.findViewById(getListViewResId());
55        listView.setAdapter(mListAdapter);
56        listView.setOnScrollListener(new OnScrollListener() {
57            @Override
58            public void onScrollStateChanged(final AbsListView view, final int scrollState) {
59                if (scrollState != SCROLL_STATE_IDLE) {
60                    ImeUtil.get().hideImeKeyboard(mContext, view);
61                }
62            }
63
64            @Override
65            public void onScroll(final AbsListView view, final int firstVisibleItem,
66                    final int visibleItemCount, final int totalItemCount) {
67            }
68        });
69        mListView = listView;
70        maybeSetEmptyView();
71        return view;
72    }
73
74    public void onContactsCursorUpdated(final Cursor data) {
75        mListAdapter.swapCursor(data);
76        if (!mListCursorInitialized) {
77            // We set the emptyView here instead of in create so that the initial load won't show
78            // the empty UI - the system handles this and doesn't do what we would like.
79            mListCursorInitialized = true;
80            maybeSetEmptyView();
81        }
82    }
83
84    /**
85     *  We don't want to show the empty view hint until BOTH conditions are met:
86     *  1. The view has been created.
87     *  2. Cursor data has been loaded once.
88     *  Due to timing when data is loaded, the view may not be ready (and vice versa). So we
89     *  are calling this method from both onContactsCursorUpdated & createView.
90     */
91    private void maybeSetEmptyView() {
92        if (mView != null && mListCursorInitialized) {
93            final ListEmptyView emptyView = (ListEmptyView) mView.findViewById(getEmptyViewResId());
94            if (emptyView != null) {
95                emptyView.setTextHint(getEmptyViewTitleResId());
96                emptyView.setImageHint(getEmptyViewImageResId());
97                final ListView listView = (ListView) mView.findViewById(getListViewResId());
98                listView.setEmptyView(emptyView);
99            }
100        }
101    }
102
103    public void invalidateList() {
104        mListAdapter.notifyDataSetChanged();
105    }
106
107    /**
108     * In order for scene transition to work, we toggle the visibility for each individual list
109     * view items so that they can be properly tracked by the scene transition manager.
110     * @param show whether the pending transition is to show or hide the list.
111     */
112    public void toggleVisibilityForPendingTransition(final boolean show, final View epicenterView) {
113        if (mListView == null) {
114            return;
115        }
116        final int childCount = mListView.getChildCount();
117        for (int i = 0; i < childCount; i++) {
118            final View childView = mListView.getChildAt(i);
119            if (childView != epicenterView) {
120                childView.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
121            }
122        }
123    }
124
125    @Override
126    public CharSequence getPageTitle(Context context) {
127        return context.getString(getPageTitleResId());
128    }
129
130    protected abstract int getLayoutResId();
131    protected abstract int getPageTitleResId();
132    protected abstract int getEmptyViewResId();
133    protected abstract int getEmptyViewTitleResId();
134    protected abstract int getEmptyViewImageResId();
135    protected abstract int getListViewResId();
136}
137