HeadersFragment.java revision 4cf79b1c4d38a190317961891f9fd052836710fd
155c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout/* 255c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * Copyright (C) 2014 The Android Open Source Project 355c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * 455c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 555c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * in compliance with the License. You may obtain a copy of the License at 655c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * 755c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * http://www.apache.org/licenses/LICENSE-2.0 855c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * 955c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * Unless required by applicable law or agreed to in writing, software distributed under the License 1055c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 1155c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * or implied. See the License for the specific language governing permissions and limitations under 1255c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * the License. 1355c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout */ 1455c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 1555c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stoutpackage android.support.v17.leanback.app; 1655c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 174cf79b1c4d38a190317961891f9fd052836710fdCraig Stoutimport android.graphics.Color; 183c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Guimport android.os.Bundle; 1955c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stoutimport android.support.v17.leanback.R; 2055c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stoutimport android.support.v17.leanback.widget.FocusHighlightHelper; 2155c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stoutimport android.support.v17.leanback.widget.ItemBridgeAdapter; 2255c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stoutimport android.support.v17.leanback.widget.Presenter; 2355c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stoutimport android.support.v17.leanback.widget.PresenterSelector; 2455c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stoutimport android.support.v17.leanback.widget.OnItemSelectedListener; 2555c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stoutimport android.support.v17.leanback.widget.Row; 263c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Guimport android.support.v17.leanback.widget.RowHeaderPresenter; 27bd80644186ff8622c565f067dc3a4136a4dc0586Dake Guimport android.support.v17.leanback.widget.SinglePresenterSelector; 283c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Guimport android.support.v17.leanback.widget.VerticalGridView; 293c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Guimport android.support.v7.widget.RecyclerView; 304cf79b1c4d38a190317961891f9fd052836710fdCraig Stoutimport android.util.TypedValue; 313c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Guimport android.view.LayoutInflater; 3255c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stoutimport android.view.View; 3355c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stoutimport android.view.ViewGroup; 342f97594742886d045ca1ce409ebc6e6e780452f6Dake Guimport android.view.View.OnLayoutChangeListener; 3555c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 362f97594742886d045ca1ce409ebc6e6e780452f6Dake Guimport java.util.ArrayList; 373c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Guimport java.util.List; 383c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu 3955c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout/** 4055c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout * An internal fragment containing a list of row headers. 4155c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout */ 42a8a3b898da49324e83ea32c3f08776a481312166Tim Kilbournpublic class HeadersFragment extends BaseRowFragment { 433c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu 443c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu interface OnHeaderClickedListener { 453c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu void onHeaderClicked(); 463c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 473c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu 4855c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout private OnItemSelectedListener mOnItemSelectedListener; 493c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu private OnHeaderClickedListener mOnHeaderClickedListener; 503c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu private boolean mShow = true; 514cf79b1c4d38a190317961891f9fd052836710fdCraig Stout private int mBackgroundColor; 524cf79b1c4d38a190317961891f9fd052836710fdCraig Stout private boolean mBackgroundColorSet; 533c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu 54bd80644186ff8622c565f067dc3a4136a4dc0586Dake Gu private static final PresenterSelector sHeaderPresenter = new SinglePresenterSelector( 55bd80644186ff8622c565f067dc3a4136a4dc0586Dake Gu new RowHeaderPresenter()); 5655c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 57a8a3b898da49324e83ea32c3f08776a481312166Tim Kilbourn public HeadersFragment() { 58bd80644186ff8622c565f067dc3a4136a4dc0586Dake Gu setPresenterSelector(sHeaderPresenter); 5955c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 6055c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 613c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu public void setOnHeaderClickedListener(OnHeaderClickedListener listener) { 623c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu mOnHeaderClickedListener = listener; 6355c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 6455c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 6555c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout public void setOnItemSelectedListener(OnItemSelectedListener listener) { 6655c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout mOnItemSelectedListener = listener; 6755c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 6855c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 6955c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout @Override 7055c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout protected void onRowSelected(ViewGroup parent, View view, int position, long id) { 7155c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout if (mOnItemSelectedListener != null) { 722f5fbc79d656fc4966119141aaef48161f08376fAndrew Wilson if (position >= 0) { 732f5fbc79d656fc4966119141aaef48161f08376fAndrew Wilson Row row = (Row) getAdapter().get(position); 742f5fbc79d656fc4966119141aaef48161f08376fAndrew Wilson mOnItemSelectedListener.onItemSelected(null, row); 752f5fbc79d656fc4966119141aaef48161f08376fAndrew Wilson } 7655c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 7755c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 7855c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout 793c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu private final ItemBridgeAdapter.AdapterListener mAdapterListener = 803c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu new ItemBridgeAdapter.AdapterListener() { 813c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu @Override 823c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu public void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) { 833c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu View headerView = viewHolder.getViewHolder().view; 843c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu headerView.setOnClickListener(new View.OnClickListener() { 853c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu @Override 863c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu public void onClick(View v) { 873c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu if (mOnHeaderClickedListener != null) { 883c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu mOnHeaderClickedListener.onHeaderClicked(); 893c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 903c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 913c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu }); 923c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu headerView.setFocusable(true); 933c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu headerView.setFocusableInTouchMode(true); 942f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu headerView.addOnLayoutChangeListener(sLayoutChangeListener); 953c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 963c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu 973c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu @Override 983c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) { 993c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu View headerView = viewHolder.getViewHolder().view; 1002f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu if (mInTransition) { 1012f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu updateHeaderViewForTransition(headerView, viewHolder.getPosition()); 1022f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu } 1033c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 1043c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu }; 1053c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu 1062f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu /** 1072f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu * Preparing headerView for transition. 1082f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu */ 1092f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu private void updateHeaderViewForTransition(View headerView, Integer position) { 1102f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu final VerticalGridView listView = getVerticalGridView(); 1112f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu if (position == listView.getSelectedPosition()) { 1122f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu headerView.setId(mReparentHeaderId); 1132f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu } else { 1142f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu headerView.setId(View.NO_ID); 1153c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 1162f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu headerView.setTag(R.id.lb_header_transition_position, position); 1173c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 1183c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu 1192f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu /** 1202f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu * Preparing all headerViews for transition. 1212f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu */ 1222f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu private void updateHeaderViewsForTransition() { 1233c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu final VerticalGridView listView = getVerticalGridView(); 1243c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu if (listView == null) { 1253c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu return; 1263c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 1273c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu final int count = listView.getChildCount(); 1283c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu for (int i = 0; i < count; i++) { 1293c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu View child = listView.getChildAt(i); 1302f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu updateHeaderViewForTransition(child, 1312f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu listView.getChildViewHolder(child).getPosition()); 1322f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu } 1332f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu } 1342f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu 1352f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu @Override 1362f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu void onTransitionStart() { 1372f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu super.onTransitionStart(); 1382f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu updateHeaderViewsForTransition(); 1392f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu } 1402f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu 1412f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu private static OnLayoutChangeListener sLayoutChangeListener = new OnLayoutChangeListener() { 1422f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu @Override 1432f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu public void onLayoutChange(View v, int left, int top, int right, int bottom, 1442f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu int oldLeft, int oldTop, int oldRight, int oldBottom) { 1452f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu v.setPivotX(0); 1462f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu v.setPivotY(v.getMeasuredHeight() / 2); 1472f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu } 1482f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu }; 1492f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu 1502f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu @Override 1512f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu protected int getLayoutResourceId() { 1522f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu return R.layout.lb_headers_fragment; 1532f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu } 1542f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu 1552f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu @Override 1562f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu public void onViewCreated(View view, Bundle savedInstanceState) { 1572f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu super.onViewCreated(view, savedInstanceState); 1584cf79b1c4d38a190317961891f9fd052836710fdCraig Stout final VerticalGridView listView = getVerticalGridView(); 1594cf79b1c4d38a190317961891f9fd052836710fdCraig Stout if (listView == null) { 1604cf79b1c4d38a190317961891f9fd052836710fdCraig Stout return; 1613c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 1624cf79b1c4d38a190317961891f9fd052836710fdCraig Stout if (getBridgeAdapter() != null) { 1634cf79b1c4d38a190317961891f9fd052836710fdCraig Stout FocusHighlightHelper.setupHeaderItemFocusHighlight(listView); 1644cf79b1c4d38a190317961891f9fd052836710fdCraig Stout } 1654cf79b1c4d38a190317961891f9fd052836710fdCraig Stout listView.setBackgroundColor(getBackgroundColor()); 1663c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 1673c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu 1683c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu void setHeadersVisiblity(boolean show) { 1693c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu mShow = show; 1703c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu final VerticalGridView listView = getVerticalGridView(); 1712f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu if (listView != null) { 1722f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu listView.setLayoutEnabled(show); 1733c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 1743c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 1753c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu 1763c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu @Override 17755c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout protected void updateAdapter() { 17855c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout super.updateAdapter(); 17955c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout ItemBridgeAdapter adapter = getBridgeAdapter(); 18055c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout if (adapter != null) { 1813c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu adapter.setAdapterListener(mAdapterListener); 1823c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu } 1833c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu if (adapter != null && getVerticalGridView() != null) { 1843c23ada8bc25a05bbaa8c479a9df72e8172c4349Dake Gu FocusHighlightHelper.setupHeaderItemFocusHighlight(getVerticalGridView()); 18555c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 18655c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout } 1874cf79b1c4d38a190317961891f9fd052836710fdCraig Stout 1884cf79b1c4d38a190317961891f9fd052836710fdCraig Stout void setBackgroundColor(int color) { 1894cf79b1c4d38a190317961891f9fd052836710fdCraig Stout mBackgroundColor = color; 1904cf79b1c4d38a190317961891f9fd052836710fdCraig Stout mBackgroundColorSet = true; 1914cf79b1c4d38a190317961891f9fd052836710fdCraig Stout 1924cf79b1c4d38a190317961891f9fd052836710fdCraig Stout if (getVerticalGridView() != null) { 1934cf79b1c4d38a190317961891f9fd052836710fdCraig Stout getVerticalGridView().setBackgroundColor(mBackgroundColor); 1944cf79b1c4d38a190317961891f9fd052836710fdCraig Stout } 1954cf79b1c4d38a190317961891f9fd052836710fdCraig Stout } 1964cf79b1c4d38a190317961891f9fd052836710fdCraig Stout 1974cf79b1c4d38a190317961891f9fd052836710fdCraig Stout int getBackgroundColor() { 1984cf79b1c4d38a190317961891f9fd052836710fdCraig Stout if (getActivity() == null) { 1994cf79b1c4d38a190317961891f9fd052836710fdCraig Stout throw new IllegalStateException("Activity must be attached"); 2004cf79b1c4d38a190317961891f9fd052836710fdCraig Stout } 2014cf79b1c4d38a190317961891f9fd052836710fdCraig Stout 2024cf79b1c4d38a190317961891f9fd052836710fdCraig Stout if (mBackgroundColorSet) { 2034cf79b1c4d38a190317961891f9fd052836710fdCraig Stout return mBackgroundColor; 2044cf79b1c4d38a190317961891f9fd052836710fdCraig Stout } 2054cf79b1c4d38a190317961891f9fd052836710fdCraig Stout 2064cf79b1c4d38a190317961891f9fd052836710fdCraig Stout TypedValue outValue = new TypedValue(); 2074cf79b1c4d38a190317961891f9fd052836710fdCraig Stout getActivity().getTheme().resolveAttribute(android.R.attr.colorBackground, outValue, true); 2084cf79b1c4d38a190317961891f9fd052836710fdCraig Stout return getResources().getColor(outValue.resourceId); 2094cf79b1c4d38a190317961891f9fd052836710fdCraig Stout } 21055c9ee4b612ffc7b4632b1e4b7b7ab4900cd47c7Craig Stout} 211