HeadersFragment.java revision d7618ab69ef591dd5342b9481c4954bfc7e9110c
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14
15package android.support.v17.leanback.app;
16
17import android.os.Bundle;
18import android.support.v17.leanback.R;
19import android.support.v17.leanback.widget.FocusHighlightHelper;
20import android.support.v17.leanback.widget.ItemBridgeAdapter;
21import android.support.v17.leanback.widget.PresenterSelector;
22import android.support.v17.leanback.widget.OnItemSelectedListener;
23import android.support.v17.leanback.widget.Row;
24import android.support.v17.leanback.widget.RowHeaderPresenter;
25import android.support.v17.leanback.widget.SinglePresenterSelector;
26import android.support.v17.leanback.widget.VerticalGridView;
27import android.util.TypedValue;
28import android.view.View;
29import android.view.ViewGroup;
30import android.view.View.OnLayoutChangeListener;
31import android.widget.FrameLayout;
32
33/**
34 * An internal fragment containing a list of row headers.
35 */
36public class HeadersFragment extends BaseRowFragment {
37
38    interface OnHeaderClickedListener {
39        void onHeaderClicked();
40    }
41
42    private OnItemSelectedListener mOnItemSelectedListener;
43    private OnHeaderClickedListener mOnHeaderClickedListener;
44    private boolean mHeadersEnabled = true;
45    private boolean mHeadersGone = false;
46    private int mBackgroundColor;
47    private boolean mBackgroundColorSet;
48
49    private static final PresenterSelector sHeaderPresenter = new SinglePresenterSelector(
50            new RowHeaderPresenter(R.layout.lb_header));
51
52    public HeadersFragment() {
53        setPresenterSelector(sHeaderPresenter);
54    }
55
56    public void setOnHeaderClickedListener(OnHeaderClickedListener listener) {
57        mOnHeaderClickedListener = listener;
58    }
59
60    public void setOnItemSelectedListener(OnItemSelectedListener listener) {
61        mOnItemSelectedListener = listener;
62    }
63
64    @Override
65    protected void onRowSelected(ViewGroup parent, View view, int position, long id) {
66        if (mOnItemSelectedListener != null) {
67            if (position >= 0) {
68                Row row = (Row) getAdapter().get(position);
69                mOnItemSelectedListener.onItemSelected(null, row);
70            } else {
71                mOnItemSelectedListener.onItemSelected(null, null);
72            }
73        }
74    }
75
76    private final ItemBridgeAdapter.AdapterListener mAdapterListener =
77            new ItemBridgeAdapter.AdapterListener() {
78        @Override
79        public void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) {
80            View headerView = viewHolder.getViewHolder().view;
81            headerView.setOnClickListener(new View.OnClickListener() {
82                @Override
83                public void onClick(View v) {
84                    if (mOnHeaderClickedListener != null) {
85                        mOnHeaderClickedListener.onHeaderClicked();
86                    }
87                }
88            });
89            headerView.setFocusable(true);
90            headerView.setFocusableInTouchMode(true);
91            if (mWrapper != null) {
92                viewHolder.itemView.addOnLayoutChangeListener(sLayoutChangeListener);
93            } else {
94                headerView.addOnLayoutChangeListener(sLayoutChangeListener);
95            }
96        }
97
98    };
99
100    private static OnLayoutChangeListener sLayoutChangeListener = new OnLayoutChangeListener() {
101        @Override
102        public void onLayoutChange(View v, int left, int top, int right, int bottom,
103            int oldLeft, int oldTop, int oldRight, int oldBottom) {
104            v.setPivotX(0);
105            v.setPivotY(v.getMeasuredHeight() / 2);
106        }
107    };
108
109    @Override
110    protected int getLayoutResourceId() {
111        return R.layout.lb_headers_fragment;
112    }
113
114    @Override
115    public void onViewCreated(View view, Bundle savedInstanceState) {
116        super.onViewCreated(view, savedInstanceState);
117        final VerticalGridView listView = getVerticalGridView();
118        if (listView == null) {
119            return;
120        }
121        if (getBridgeAdapter() != null) {
122            FocusHighlightHelper.setupHeaderItemFocusHighlight(listView);
123        }
124        listView.setBackgroundColor(getBackgroundColor());
125        updateListViewVisibility();
126    }
127
128    private void updateListViewVisibility() {
129        final VerticalGridView listView = getVerticalGridView();
130        if (listView != null) {
131            listView.setVisibility(mHeadersGone ? View.GONE : View.VISIBLE);
132            if (!mHeadersGone) {
133                if (mHeadersEnabled) {
134                    listView.setChildrenVisibility(View.VISIBLE);
135                } else {
136                    listView.setChildrenVisibility(View.INVISIBLE);
137                }
138            }
139        }
140    }
141
142    void setHeadersEnabled(boolean enabled) {
143        mHeadersEnabled = enabled;
144        updateListViewVisibility();
145    }
146
147    void setHeadersGone(boolean gone) {
148        mHeadersGone = gone;
149        updateListViewVisibility();
150    }
151
152    // Wrapper needed because of conflict between RecyclerView's use of alpha
153    // for ADD animations, and RowHeaderPresnter's use of alpha for selected level.
154    private final ItemBridgeAdapter.Wrapper mWrapper = new ItemBridgeAdapter.Wrapper() {
155        @Override
156        public void wrap(View wrapper, View wrapped) {
157            ((FrameLayout) wrapper).addView(wrapped);
158        }
159
160        @Override
161        public View createWrapper(View root) {
162            return new FrameLayout(root.getContext());
163        }
164    };
165    @Override
166    protected void updateAdapter() {
167        super.updateAdapter();
168        ItemBridgeAdapter adapter = getBridgeAdapter();
169        if (adapter != null) {
170            adapter.setAdapterListener(mAdapterListener);
171            adapter.setWrapper(mWrapper);
172        }
173        if (adapter != null && getVerticalGridView() != null) {
174            FocusHighlightHelper.setupHeaderItemFocusHighlight(getVerticalGridView());
175        }
176    }
177
178    void setBackgroundColor(int color) {
179        mBackgroundColor = color;
180        mBackgroundColorSet = true;
181
182        if (getVerticalGridView() != null) {
183            getVerticalGridView().setBackgroundColor(mBackgroundColor);
184        }
185    }
186
187    int getBackgroundColor() {
188        if (getActivity() == null) {
189            throw new IllegalStateException("Activity must be attached");
190        }
191
192        if (mBackgroundColorSet) {
193            return mBackgroundColor;
194        }
195
196        TypedValue outValue = new TypedValue();
197        getActivity().getTheme().resolveAttribute(R.attr.defaultBrandColor, outValue, true);
198        return getResources().getColor(outValue.resourceId);
199    }
200}
201