blob: 418987669049c5b551c55b3cd6b2befed99d9438 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package androidx.leanback.app;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.leanback.R;
import androidx.leanback.transition.TransitionHelper;
import androidx.leanback.util.StateMachine.State;
import androidx.leanback.widget.BrowseFrameLayout;
import androidx.leanback.widget.ObjectAdapter;
import androidx.leanback.widget.OnChildLaidOutListener;
import androidx.leanback.widget.OnItemViewClickedListener;
import androidx.leanback.widget.OnItemViewSelectedListener;
import androidx.leanback.widget.Presenter;
import androidx.leanback.widget.Row;
import androidx.leanback.widget.RowPresenter;
import androidx.leanback.widget.VerticalGridPresenter;
/**
* A fragment for creating leanback vertical grids.
*
* <p>Renders a vertical grid of objects given a {@link VerticalGridPresenter} and
* an {@link ObjectAdapter}.
*/
public class VerticalGridSupportFragment extends BaseSupportFragment {
static final String TAG = "VerticalGF";
static final boolean DEBUG = false;
private ObjectAdapter mAdapter;
private VerticalGridPresenter mGridPresenter;
VerticalGridPresenter.ViewHolder mGridViewHolder;
OnItemViewSelectedListener mOnItemViewSelectedListener;
private OnItemViewClickedListener mOnItemViewClickedListener;
private Object mSceneAfterEntranceTransition;
private int mSelectedPosition = -1;
/**
* State to setEntranceTransitionState(false)
*/
final State STATE_SET_ENTRANCE_START_STATE = new State("SET_ENTRANCE_START_STATE") {
@Override
public void run() {
setEntranceTransitionState(false);
}
};
@Override
void createStateMachineStates() {
super.createStateMachineStates();
mStateMachine.addState(STATE_SET_ENTRANCE_START_STATE);
}
@Override
void createStateMachineTransitions() {
super.createStateMachineTransitions();
mStateMachine.addTransition(STATE_ENTRANCE_ON_PREPARED,
STATE_SET_ENTRANCE_START_STATE, EVT_ON_CREATEVIEW);
}
/**
* Sets the grid presenter.
*/
public void setGridPresenter(@NonNull VerticalGridPresenter gridPresenter) {
if (gridPresenter == null) {
throw new IllegalArgumentException("Grid presenter may not be null");
}
mGridPresenter = gridPresenter;
mGridPresenter.setOnItemViewSelectedListener(mViewSelectedListener);
if (mOnItemViewClickedListener != null) {
mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener);
}
}
/**
* Returns the grid presenter.
*/
@Nullable
public VerticalGridPresenter getGridPresenter() {
return mGridPresenter;
}
/**
* Sets the object adapter for the fragment.
*/
public void setAdapter(@Nullable ObjectAdapter adapter) {
mAdapter = adapter;
updateAdapter();
}
/**
* Returns the object adapter.
*/
@Nullable
public ObjectAdapter getAdapter() {
return mAdapter;
}
final private OnItemViewSelectedListener mViewSelectedListener =
new OnItemViewSelectedListener() {
@Override
public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
RowPresenter.ViewHolder rowViewHolder, Row row) {
int position = mGridViewHolder.getGridView().getSelectedPosition();
if (DEBUG) Log.v(TAG, "grid selected position " + position);
gridOnItemSelected(position);
if (mOnItemViewSelectedListener != null) {
mOnItemViewSelectedListener.onItemSelected(itemViewHolder, item,
rowViewHolder, row);
}
}
};
final private OnChildLaidOutListener mChildLaidOutListener =
new OnChildLaidOutListener() {
@Override
public void onChildLaidOut(
@NonNull ViewGroup parent,
@NonNull View view,
int position,
long id
) {
if (position == 0) {
showOrHideTitle();
}
}
};
/**
* Sets an item selection listener.
*/
public void setOnItemViewSelectedListener(@Nullable OnItemViewSelectedListener listener) {
mOnItemViewSelectedListener = listener;
}
void gridOnItemSelected(int position) {
if (position != mSelectedPosition) {
mSelectedPosition = position;
showOrHideTitle();
}
}
void showOrHideTitle() {
if (mGridViewHolder.getGridView().findViewHolderForAdapterPosition(mSelectedPosition)
== null) {
return;
}
if (!mGridViewHolder.getGridView().hasPreviousViewInSameRow(mSelectedPosition)) {
showTitle(true);
} else {
showTitle(false);
}
}
/**
* Sets an item clicked listener.
*/
public void setOnItemViewClickedListener(@Nullable OnItemViewClickedListener listener) {
mOnItemViewClickedListener = listener;
if (mGridPresenter != null) {
mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener);
}
}
/**
* Returns the item clicked listener.
*/
@Nullable
public OnItemViewClickedListener getOnItemViewClickedListener() {
return mOnItemViewClickedListener;
}
@Override
@Nullable
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_vertical_grid_fragment,
container, false);
ViewGroup gridFrame = (ViewGroup) root.findViewById(R.id.grid_frame);
installTitleView(inflater, gridFrame, savedInstanceState);
getProgressBarManager().setRootView(root);
ViewGroup gridDock = (ViewGroup) root.findViewById(R.id.browse_grid_dock);
mGridViewHolder = mGridPresenter.onCreateViewHolder(gridDock);
gridDock.addView(mGridViewHolder.view);
mGridViewHolder.getGridView().setOnChildLaidOutListener(mChildLaidOutListener);
mSceneAfterEntranceTransition = TransitionHelper.createScene(gridDock, new Runnable() {
@Override
public void run() {
setEntranceTransitionState(true);
}
});
updateAdapter();
return root;
}
private void setupFocusSearchListener() {
BrowseFrameLayout browseFrameLayout = (BrowseFrameLayout) getView().findViewById(
R.id.grid_frame);
browseFrameLayout.setOnFocusSearchListener(getTitleHelper().getOnFocusSearchListener());
}
@Override
public void onStart() {
super.onStart();
setupFocusSearchListener();
}
@Override
public void onDestroyView() {
super.onDestroyView();
mGridViewHolder.getGridView().swapAdapter(null, true);
mGridViewHolder = null;
mSceneAfterEntranceTransition = null;
}
/**
* Sets the selected item position.
*/
public void setSelectedPosition(int position) {
mSelectedPosition = position;
if(mGridViewHolder != null && mGridViewHolder.getGridView().getAdapter() != null) {
mGridViewHolder.getGridView().setSelectedPositionSmooth(position);
}
}
private void updateAdapter() {
if (mGridViewHolder != null) {
mGridPresenter.onBindViewHolder(mGridViewHolder, mAdapter);
if (mSelectedPosition != -1) {
mGridViewHolder.getGridView().setSelectedPosition(mSelectedPosition);
}
}
}
@Override
@NonNull
protected Object createEntranceTransition() {
return TransitionHelper.loadTransition(getContext(),
R.transition.lb_vertical_grid_entrance_transition);
}
@Override
protected void runEntranceTransition(@Nullable Object entranceTransition) {
TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
}
void setEntranceTransitionState(boolean afterTransition) {
mGridPresenter.setEntranceTransitionState(mGridViewHolder, afterTransition);
}
}