public class

BaseSupportFragment

extends BrandedSupportFragment

 java.lang.Object

androidx.fragment.app.Fragment

androidx.leanback.app.BrandedSupportFragment

↳androidx.leanback.app.BaseSupportFragment

Subclasses:

BrowseSupportFragment, DetailsSupportFragment, VerticalGridSupportFragment

Gradle dependencies

compile group: 'androidx.leanback', name: 'leanback', version: '1.2.0-alpha02'

  • groupId: androidx.leanback
  • artifactId: leanback
  • version: 1.2.0-alpha02

Artifact androidx.leanback:leanback:1.2.0-alpha02 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.leanback:leanback com.android.support:leanback-v17

Androidx class mapping:

androidx.leanback.app.BaseSupportFragment android.support.v17.leanback.app.BaseSupportFragment

Overview

Base class for leanback Fragments. This class is not intended to be subclassed by apps.

Summary

Fields
from FragmentmPreviousWho
Methods
protected java.lang.ObjectcreateEntranceTransition()

Create entrance transition.

public final ProgressBarManagergetProgressBarManager()

Returns the ProgressBarManager.

public voidonCreate(Bundle savedInstanceState)

Called to do initial creation of a fragment.

public voidonDestroyView()

Called when the view previously created by Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle) has been detached from the fragment.

protected voidonEntranceTransitionEnd()

Callback when entrance transition is ended.

protected voidonEntranceTransitionPrepare()

Callback when entrance transition is prepared.

protected voidonEntranceTransitionStart()

Callback when entrance transition is started.

public voidonViewCreated(View view, Bundle savedInstanceState)

Called immediately after Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle) has returned, but before any saved state has been restored in to the view.

public voidprepareEntranceTransition()

Enables entrance transition.

protected voidrunEntranceTransition(java.lang.Object entranceTransition)

Run entrance transition.

public voidstartEntranceTransition()

When fragment finishes loading data, it should call startEntranceTransition() to execute the entrance transition.

from BrandedSupportFragmentgetBadgeDrawable, getSearchAffordanceColor, getSearchAffordanceColors, getTitle, getTitleView, getTitleViewAdapter, installTitleView, isShowingTitle, onInflateTitleView, onPause, onResume, onSaveInstanceState, onStart, setBadgeDrawable, setOnSearchClickedListener, setSearchAffordanceColor, setSearchAffordanceColors, setTitle, setTitleView, showTitle, showTitle
from Fragmentdump, equals, getActivity, getAllowEnterTransitionOverlap, getAllowReturnTransitionOverlap, getArguments, getChildFragmentManager, getContext, getDefaultViewModelCreationExtras, getDefaultViewModelProviderFactory, getEnterTransition, getExitTransition, getFragmentManager, getHost, getId, getLayoutInflater, getLayoutInflater, getLifecycle, getLoaderManager, getParentFragment, getParentFragmentManager, getReenterTransition, getResources, getRetainInstance, getReturnTransition, getSavedStateRegistry, getSharedElementEnterTransition, getSharedElementReturnTransition, getString, getString, getTag, getTargetFragment, getTargetRequestCode, getText, getUserVisibleHint, getView, getViewLifecycleOwner, getViewLifecycleOwnerLiveData, getViewModelStore, hashCode, hasOptionsMenu, instantiate, instantiate, isAdded, isDetached, isHidden, isInLayout, isMenuVisible, isRemoving, isResumed, isStateSaved, isVisible, onActivityCreated, onActivityResult, onAttach, onAttach, onAttachFragment, onConfigurationChanged, onContextItemSelected, onCreateAnimation, onCreateAnimator, onCreateContextMenu, onCreateOptionsMenu, onCreateView, onDestroy, onDestroyOptionsMenu, onDetach, onGetLayoutInflater, onHiddenChanged, onInflate, onInflate, onLowMemory, onMultiWindowModeChanged, onOptionsItemSelected, onOptionsMenuClosed, onPictureInPictureModeChanged, onPrepareOptionsMenu, onPrimaryNavigationFragmentChanged, onRequestPermissionsResult, onStop, onViewStateRestored, postponeEnterTransition, postponeEnterTransition, registerForActivityResult, registerForActivityResult, registerForContextMenu, requestPermissions, requireActivity, requireArguments, requireContext, requireFragmentManager, requireHost, requireParentFragment, requireView, setAllowEnterTransitionOverlap, setAllowReturnTransitionOverlap, setArguments, setEnterSharedElementCallback, setEnterTransition, setExitSharedElementCallback, setExitTransition, setHasOptionsMenu, setInitialSavedState, setMenuVisibility, setReenterTransition, setRetainInstance, setReturnTransition, setSharedElementEnterTransition, setSharedElementReturnTransition, setTargetFragment, setUserVisibleHint, shouldShowRequestPermissionRationale, startActivity, startActivity, startActivityForResult, startActivityForResult, startIntentSenderForResult, startPostponedEnterTransition, toString, unregisterForContextMenu
from java.lang.Objectclone, finalize, getClass, notify, notifyAll, wait, wait, wait

Methods

public void onCreate(Bundle savedInstanceState)

Called to do initial creation of a fragment. This is called after Fragment.onAttach(Activity) and before Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle).

Note that this can be called while the fragment's activity is still in the process of being created. As such, you can not rely on things like the activity's content view hierarchy being initialized at this point. If you want to do work once the activity itself is created, add a LifecycleObserver on the activity's Lifecycle, removing it when it receives the callback.

Any restored child fragments will be created before the base Fragment.onCreate method returns.

Parameters:

savedInstanceState: If the fragment is being re-created from a previous saved state, this is the state.

public void onViewCreated(View view, Bundle savedInstanceState)

Called immediately after Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle) has returned, but before any saved state has been restored in to the view. This gives subclasses a chance to initialize themselves once they know their view hierarchy has been completely created. The fragment's view hierarchy is not however attached to its parent at this point.

Parameters:

view: The View returned by Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle).
savedInstanceState: If non-null, this fragment is being re-constructed from a previous saved state as given here.

public void onDestroyView()

Called when the view previously created by Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle) has been detached from the fragment. The next time the fragment needs to be displayed, a new view will be created. This is called after Fragment.onStop() and before Fragment.onDestroy(). It is called regardless of whether Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle) returned a non-null view. Internally it is called after the view's state has been saved but before it has been removed from its parent.

public void prepareEntranceTransition()

Enables entrance transition.

Entrance transition is the standard slide-in transition that shows rows of data in browse screen and details screen.

The method is ignored before LOLLIPOP (API21).

This method must be called in or before onCreate(). Typically entrance transition should be enabled when savedInstance is null so that fragment restored from instanceState does not run an extra entrance transition. When the entrance transition is enabled, the fragment will make headers and content hidden initially. When data of rows are ready, app must call BaseSupportFragment.startEntranceTransition() to kick off the transition, otherwise the rows will be invisible forever.

It is similar to android:windowsEnterTransition and can be considered a late-executed android:windowsEnterTransition controlled by app. There are two reasons that app needs it:

  • Workaround the problem that activity transition is not available between launcher and app. Browse activity must programmatically start the slide-in transition.
  • Separates DetailsOverviewRow transition from other rows transition. So that the DetailsOverviewRow transition can be executed earlier without waiting for all rows to be loaded.

Transition object is returned by createEntranceTransition(). Typically the app does not need override the default transition that browse and details provides.

protected java.lang.Object createEntranceTransition()

Create entrance transition. Subclass can override to load transition from resource or construct manually. Typically app does not need to override the default transition that browse and details provides.

protected void runEntranceTransition(java.lang.Object entranceTransition)

Run entrance transition. Subclass may use TransitionManager to perform go(Scene) or beginDelayedTransition(). App should not override the default implementation of browse and details fragment.

protected void onEntranceTransitionPrepare()

Callback when entrance transition is prepared. This is when fragment should stop user input and animations.

protected void onEntranceTransitionStart()

Callback when entrance transition is started. This is when fragment should stop processing layout.

protected void onEntranceTransitionEnd()

Callback when entrance transition is ended.

public void startEntranceTransition()

When fragment finishes loading data, it should call startEntranceTransition() to execute the entrance transition. startEntranceTransition() will start transition only if both two conditions are satisfied:

  • prepareEntranceTransition() was called.
  • has not executed entrance transition yet.

If startEntranceTransition() is called before onViewCreated(), it will be pending and executed when view is created.

public final ProgressBarManager getProgressBarManager()

Returns the ProgressBarManager.

Returns:

The ProgressBarManager.

Source

/*
 * 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.annotation.SuppressLint;
import android.os.Bundle;
import android.view.View;
import android.view.ViewTreeObserver;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.leanback.transition.TransitionHelper;
import androidx.leanback.transition.TransitionListener;
import androidx.leanback.util.StateMachine;
import androidx.leanback.util.StateMachine.Condition;
import androidx.leanback.util.StateMachine.Event;
import androidx.leanback.util.StateMachine.State;

/**
 * Base class for leanback Fragments. This class is not intended to be subclassed by apps.
 */
@SuppressWarnings("FragmentNotInstantiable")
public class BaseSupportFragment extends BrandedSupportFragment {

    /**
     * The start state for all
     */
    final State STATE_START = new State("START", true, false);

    /**
     * Initial State for ENTRNACE transition.
     */
    final State STATE_ENTRANCE_INIT = new State("ENTRANCE_INIT");

    /**
     * prepareEntranceTransition is just called, but view not ready yet. We can enable the
     * busy spinner.
     */
    final State STATE_ENTRANCE_ON_PREPARED = new State("ENTRANCE_ON_PREPARED", true, false) {
        @Override
        public void run() {
            mProgressBarManager.show();
        }
    };

    /**
     * prepareEntranceTransition is called and main content view to slide in was created, so we can
     * call {@link #onEntranceTransitionPrepare}. Note that we dont set initial content to invisible
     * in this State, the process is very different in subclass, e.g. BrowseSupportFragment hide header
     * views and hide main fragment view in two steps.
     */
    final State STATE_ENTRANCE_ON_PREPARED_ON_CREATEVIEW = new State(
            "ENTRANCE_ON_PREPARED_ON_CREATEVIEW") {
        @Override
        public void run() {
            onEntranceTransitionPrepare();
        }
    };

    /**
     * execute the entrance transition.
     */
    final State STATE_ENTRANCE_PERFORM = new State("STATE_ENTRANCE_PERFORM") {
        @Override
        public void run() {
            mProgressBarManager.hide();
            onExecuteEntranceTransition();
        }
    };

    /**
     * execute onEntranceTransitionEnd.
     */
    final State STATE_ENTRANCE_ON_ENDED = new State("ENTRANCE_ON_ENDED") {
        @Override
        public void run() {
            onEntranceTransitionEnd();
        }
    };

    /**
     * either entrance transition completed or skipped
     */
    final State STATE_ENTRANCE_COMPLETE = new State("ENTRANCE_COMPLETE", true, false);

    /**
     * Event fragment.onCreate()
     */
    final Event EVT_ON_CREATE = new Event("onCreate");

    /**
     * Event fragment.onViewCreated()
     */
    final Event EVT_ON_CREATEVIEW = new Event("onCreateView");

    /**
     * Event for {@link #prepareEntranceTransition()} is called.
     */
    final Event EVT_PREPARE_ENTRANCE = new Event("prepareEntranceTransition");

    /**
     * Event for {@link #startEntranceTransition()} is called.
     */
    final Event EVT_START_ENTRANCE = new Event("startEntranceTransition");

    /**
     * Event for entrance transition is ended through Transition listener.
     */
    final Event EVT_ENTRANCE_END = new Event("onEntranceTransitionEnd");

    /**
     * Event for skipping entrance transition if not supported.
     */
    final Condition COND_TRANSITION_NOT_SUPPORTED = new Condition("EntranceTransitionNotSupport") {
        @Override
        public boolean canProceed() {
            return !TransitionHelper.systemSupportsEntranceTransitions();
        }
    };

    final StateMachine mStateMachine = new StateMachine();

    Object mEntranceTransition;
    final ProgressBarManager mProgressBarManager = new ProgressBarManager();

    @SuppressLint("ValidFragment")
    BaseSupportFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        createStateMachineStates();
        createStateMachineTransitions();
        mStateMachine.start();
        super.onCreate(savedInstanceState);
        mStateMachine.fireEvent(EVT_ON_CREATE);
    }

    void createStateMachineStates() {
        mStateMachine.addState(STATE_START);
        mStateMachine.addState(STATE_ENTRANCE_INIT);
        mStateMachine.addState(STATE_ENTRANCE_ON_PREPARED);
        mStateMachine.addState(STATE_ENTRANCE_ON_PREPARED_ON_CREATEVIEW);
        mStateMachine.addState(STATE_ENTRANCE_PERFORM);
        mStateMachine.addState(STATE_ENTRANCE_ON_ENDED);
        mStateMachine.addState(STATE_ENTRANCE_COMPLETE);
    }

    void createStateMachineTransitions() {
        mStateMachine.addTransition(STATE_START, STATE_ENTRANCE_INIT, EVT_ON_CREATE);
        mStateMachine.addTransition(STATE_ENTRANCE_INIT, STATE_ENTRANCE_COMPLETE,
                COND_TRANSITION_NOT_SUPPORTED);
        mStateMachine.addTransition(STATE_ENTRANCE_INIT, STATE_ENTRANCE_COMPLETE,
                EVT_ON_CREATEVIEW);
        mStateMachine.addTransition(STATE_ENTRANCE_INIT, STATE_ENTRANCE_ON_PREPARED,
                EVT_PREPARE_ENTRANCE);
        mStateMachine.addTransition(STATE_ENTRANCE_ON_PREPARED,
                STATE_ENTRANCE_ON_PREPARED_ON_CREATEVIEW,
                EVT_ON_CREATEVIEW);
        mStateMachine.addTransition(STATE_ENTRANCE_ON_PREPARED,
                STATE_ENTRANCE_PERFORM,
                EVT_START_ENTRANCE);
        mStateMachine.addTransition(STATE_ENTRANCE_ON_PREPARED_ON_CREATEVIEW,
                STATE_ENTRANCE_PERFORM);
        mStateMachine.addTransition(STATE_ENTRANCE_PERFORM,
                STATE_ENTRANCE_ON_ENDED,
                EVT_ENTRANCE_END);
        mStateMachine.addTransition(STATE_ENTRANCE_ON_ENDED, STATE_ENTRANCE_COMPLETE);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mStateMachine.fireEvent(EVT_ON_CREATEVIEW);
    }

    @Override
    public void onDestroyView() {
        mProgressBarManager.setRootView(null);
        mProgressBarManager.setProgressBarView(null);
        super.onDestroyView();
    }

    /**
     * Enables entrance transition.<p>
     * Entrance transition is the standard slide-in transition that shows rows of data in
     * browse screen and details screen.
     * <p>
     * The method is ignored before LOLLIPOP (API21).
     * <p>
     * This method must be called in or
     * before onCreate().  Typically entrance transition should be enabled when savedInstance is
     * null so that fragment restored from instanceState does not run an extra entrance transition.
     * When the entrance transition is enabled, the fragment will make headers and content
     * hidden initially.
     * When data of rows are ready, app must call {@link #startEntranceTransition()} to kick off
     * the transition, otherwise the rows will be invisible forever.
     * <p>
     * It is similar to android:windowsEnterTransition and can be considered a late-executed
     * android:windowsEnterTransition controlled by app.  There are two reasons that app needs it:
     * <ul>
     * <li> Workaround the problem that activity transition is not available between launcher and
     * app.  Browse activity must programmatically start the slide-in transition.</li>
     * <li> Separates DetailsOverviewRow transition from other rows transition.  So that
     * the DetailsOverviewRow transition can be executed earlier without waiting for all rows
     * to be loaded.</li>
     * </ul>
     * <p>
     * Transition object is returned by createEntranceTransition().  Typically the app does not need
     * override the default transition that browse and details provides.
     */
    public void prepareEntranceTransition() {
        mStateMachine.fireEvent(EVT_PREPARE_ENTRANCE);
    }

    /**
     * Create entrance transition.  Subclass can override to load transition from
     * resource or construct manually.  Typically app does not need to
     * override the default transition that browse and details provides.
     */
    protected Object createEntranceTransition() {
        return null;
    }

    /**
     * Run entrance transition.  Subclass may use TransitionManager to perform
     * go(Scene) or beginDelayedTransition().  App should not override the default
     * implementation of browse and details fragment.
     */
    protected void runEntranceTransition(Object entranceTransition) {
    }

    /**
     * Callback when entrance transition is prepared.  This is when fragment should
     * stop user input and animations.
     */
    protected void onEntranceTransitionPrepare() {
    }

    /**
     * Callback when entrance transition is started.  This is when fragment should
     * stop processing layout.
     */
    protected void onEntranceTransitionStart() {
    }

    /**
     * Callback when entrance transition is ended.
     */
    protected void onEntranceTransitionEnd() {
    }

    /**
     * When fragment finishes loading data, it should call startEntranceTransition()
     * to execute the entrance transition.
     * startEntranceTransition() will start transition only if both two conditions
     * are satisfied:
     * <ul>
     * <li> prepareEntranceTransition() was called.</li>
     * <li> has not executed entrance transition yet.</li>
     * </ul>
     * <p>
     * If startEntranceTransition() is called before onViewCreated(), it will be pending
     * and executed when view is created.
     */
    public void startEntranceTransition() {
        mStateMachine.fireEvent(EVT_START_ENTRANCE);
    }

    void onExecuteEntranceTransition() {
        // wait till views get their initial position before start transition
        final View view = getView();
        if (view == null) {
            // fragment view destroyed, transition not needed
            return;
        }
        view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                view.getViewTreeObserver().removeOnPreDrawListener(this);
                if (getContext() == null || getView() == null) {
                    // bail out if fragment is destroyed immediately after startEntranceTransition
                    return true;
                }
                internalCreateEntranceTransition();
                onEntranceTransitionStart();
                if (mEntranceTransition != null) {
                    runEntranceTransition(mEntranceTransition);
                } else {
                    mStateMachine.fireEvent(EVT_ENTRANCE_END);
                }
                return false;
            }
        });
        view.invalidate();
    }

    void internalCreateEntranceTransition() {
        mEntranceTransition = createEntranceTransition();
        if (mEntranceTransition == null) {
            return;
        }
        TransitionHelper.addTransitionListener(mEntranceTransition, new TransitionListener() {
            @Override
            public void onTransitionEnd(Object transition) {
                mEntranceTransition = null;
                mStateMachine.fireEvent(EVT_ENTRANCE_END);
            }
        });
    }

    /**
     * Returns the {@link ProgressBarManager}.
     * @return The {@link ProgressBarManager}.
     */
    public final ProgressBarManager getProgressBarManager() {
        return mProgressBarManager;
    }
}