diff options
Diffstat (limited to 'common/src/com/android/tv/common/ui')
9 files changed, 408 insertions, 292 deletions
diff --git a/common/src/com/android/tv/common/ui/setup/OnActionClickListener.java b/common/src/com/android/tv/common/ui/setup/OnActionClickListener.java index 392d489f..6f088c0b 100644 --- a/common/src/com/android/tv/common/ui/setup/OnActionClickListener.java +++ b/common/src/com/android/tv/common/ui/setup/OnActionClickListener.java @@ -18,14 +18,12 @@ package com.android.tv.common.ui.setup; import android.os.Bundle; -/** - * A listener for the action click. - */ +/** A listener for the action click. */ public interface OnActionClickListener { /** * Called when the action is clicked. - * <p> - * The method should return {@code true} if the action is handled, otherwise {@code false}. + * + * <p>The method should return {@code true} if the action is handled, otherwise {@code false}. * * @param category The action category. * @param id The action id. diff --git a/common/src/com/android/tv/common/ui/setup/SetupActionHelper.java b/common/src/com/android/tv/common/ui/setup/SetupActionHelper.java index 7ee06faf..8a7dbd70 100644 --- a/common/src/com/android/tv/common/ui/setup/SetupActionHelper.java +++ b/common/src/com/android/tv/common/ui/setup/SetupActionHelper.java @@ -22,46 +22,45 @@ import android.util.Log; import android.view.View; import android.view.View.OnClickListener; -/** - * Helper class for the execution in the fragment. - */ +/** Helper class for the execution in the fragment. */ public class SetupActionHelper { private static final String TAG = "SetupActionHelper"; - /** - * Executes the action. - */ + /** Executes the action. */ public static boolean onActionClick(Fragment fragment, String category, int actionId) { return onActionClick(fragment, category, actionId, null); } - /** - * Executes the action. - */ - public static boolean onActionClick(Fragment fragment, String category, int actionId, - Bundle params) { + /** Executes the action. */ + public static boolean onActionClick( + Fragment fragment, String category, int actionId, Bundle params) { if (fragment.getActivity() instanceof OnActionClickListener) { - return ((OnActionClickListener) fragment.getActivity()).onActionClick(category, - actionId, params); + return ((OnActionClickListener) fragment.getActivity()) + .onActionClick(category, actionId, params); } - Log.e(TAG, "Activity can't handle the action: {category=" + category + ", actionId=" - + actionId + ", params=" + params + "}"); + Log.e( + TAG, + "Activity can't handle the action: {category=" + + category + + ", actionId=" + + actionId + + ", params=" + + params + + "}"); return false; } - /** - * Creates an {@link OnClickListener} to handle the action. - */ - public static OnClickListener createOnClickListenerForAction(Fragment fragment, String category, - int actionId, Bundle params) { + /** Creates an {@link OnClickListener} to handle the action. */ + public static OnClickListener createOnClickListenerForAction( + Fragment fragment, String category, int actionId, Bundle params) { return new OnActionClickListenerForAction(fragment, category, actionId, params); } /** * The {@link OnClickListener} for the view. - * <p> - * Note that this class should be used only for the views in the {@code mFragment} to avoid the - * leak of mFragment. + * + * <p>Note that this class should be used only for the views in the {@code mFragment} to avoid + * the leak of mFragment. */ private static class OnActionClickListenerForAction implements OnClickListener { private final Fragment mFragment; @@ -69,8 +68,8 @@ public class SetupActionHelper { private final int mActionId; private final Bundle mParams; - OnActionClickListenerForAction(Fragment fragment, String category, int actionId, - Bundle params) { + OnActionClickListenerForAction( + Fragment fragment, String category, int actionId, Bundle params) { mFragment = fragment; mCategory = category; mActionId = actionId; @@ -83,5 +82,5 @@ public class SetupActionHelper { } } - private SetupActionHelper() { } + private SetupActionHelper() {} } diff --git a/common/src/com/android/tv/common/ui/setup/SetupActivity.java b/common/src/com/android/tv/common/ui/setup/SetupActivity.java index 2b381a6e..67418ce0 100644 --- a/common/src/com/android/tv/common/ui/setup/SetupActivity.java +++ b/common/src/com/android/tv/common/ui/setup/SetupActivity.java @@ -28,7 +28,6 @@ import android.transition.Transition; import android.transition.TransitionInflater; import android.view.View; import android.view.ViewTreeObserver.OnPreDrawListener; - import com.android.tv.common.R; import com.android.tv.common.WeakHandler; import com.android.tv.common.ui.setup.animation.SetupAnimationHelper; @@ -51,23 +50,28 @@ public abstract class SetupActivity extends Activity implements OnActionClickLis super.onCreate(savedInstanceState); SetupAnimationHelper.initialize(this); setContentView(R.layout.activity_setup); - mFragmentTransitionDuration = getResources().getInteger( - R.integer.setup_fragment_transition_duration); + mFragmentTransitionDuration = + getResources().getInteger(R.integer.setup_fragment_transition_duration); // Show initial fragment only when the saved state is not restored, because the last // fragment is restored if savesInstanceState is not null. if (savedInstanceState == null) { // This is the workaround to show the first fragment with delay to show the fragment // enter transition. See http://b/26255145 - getWindow().getDecorView().getViewTreeObserver().addOnPreDrawListener( - new OnPreDrawListener() { - @Override - public boolean onPreDraw() { - getWindow().getDecorView().getViewTreeObserver() - .removeOnPreDrawListener(this); - showInitialFragment(); - return true; - } - }); + getWindow() + .getDecorView() + .getViewTreeObserver() + .addOnPreDrawListener( + new OnPreDrawListener() { + @Override + public boolean onPreDraw() { + getWindow() + .getDecorView() + .getViewTreeObserver() + .removeOnPreDrawListener(this); + showInitialFragment(); + return true; + } + }); } else { mShowInitialFragment = false; } @@ -76,8 +80,8 @@ public abstract class SetupActivity extends Activity implements OnActionClickLis /** * The inherited class should provide the initial fragment to show. * - * <p>If this method returns {@code null} during {@link #onCreate}, then call - * {@link #showInitialFragment} explicitly later with non null initial fragment. + * <p>If this method returns {@code null} during {@link #onCreate}, then call {@link + * #showInitialFragment} explicitly later with non null initial fragment. */ protected abstract Fragment onCreateInitialFragment(); @@ -98,16 +102,15 @@ public abstract class SetupActivity extends Activity implements OnActionClickLis } } - /** - * Shows the given fragment. - */ + /** Shows the given fragment. */ protected FragmentTransaction showFragment(Fragment fragment, boolean addToBackStack) { FragmentTransaction ft = getFragmentManager().beginTransaction(); if (fragment instanceof SetupFragment) { int[] sharedElements = ((SetupFragment) fragment).getSharedElementIds(); if (sharedElements != null && sharedElements.length > 0) { - Transition sharedTransition = TransitionInflater.from(this) - .inflateTransition(R.transition.transition_action_background); + Transition sharedTransition = + TransitionInflater.from(this) + .inflateTransition(R.transition.transition_action_background); sharedTransition.setDuration(getSharedElementTransitionDuration()); SetupAnimationHelper.applyAnimationTimeScale(sharedTransition); fragment.setSharedElementEnterTransition(sharedTransition); @@ -143,9 +146,9 @@ public abstract class SetupActivity extends Activity implements OnActionClickLis /** * Override this method if the inherited class wants to handle the action. - * <p> - * The override method should return {@code true} if the action is handled, otherwise - * {@code false}. + * + * <p>The override method should return {@code true} if the action is handled, otherwise {@code + * false}. */ protected boolean executeAction(String category, int actionId, Bundle params) { return false; diff --git a/common/src/com/android/tv/common/ui/setup/SetupFragment.java b/common/src/com/android/tv/common/ui/setup/SetupFragment.java index d2b9d7c8..7d47548d 100644 --- a/common/src/com/android/tv/common/ui/setup/SetupFragment.java +++ b/common/src/com/android/tv/common/ui/setup/SetupFragment.java @@ -26,22 +26,25 @@ import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; - import com.android.tv.common.ui.setup.animation.FadeAndShortSlide; import com.android.tv.common.ui.setup.animation.SetupAnimationHelper; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -/** - * A fragment which slides when it is entering/exiting. - */ +/** A fragment which slides when it is entering/exiting. */ public abstract class SetupFragment extends Fragment { @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, - value = {FRAGMENT_ENTER_TRANSITION, FRAGMENT_EXIT_TRANSITION, - FRAGMENT_REENTER_TRANSITION, FRAGMENT_RETURN_TRANSITION}) + @IntDef( + flag = true, + value = { + FRAGMENT_ENTER_TRANSITION, + FRAGMENT_EXIT_TRANSITION, + FRAGMENT_REENTER_TRANSITION, + FRAGMENT_RETURN_TRANSITION + } + ) public @interface FragmentTransitionType {} + public static final int FRAGMENT_ENTER_TRANSITION = 0x01; public static final int FRAGMENT_EXIT_TRANSITION = FRAGMENT_ENTER_TRANSITION << 1; public static final int FRAGMENT_REENTER_TRANSITION = FRAGMENT_ENTER_TRANSITION << 2; @@ -49,50 +52,50 @@ public abstract class SetupFragment extends Fragment { private boolean mEnterTransitionRunning; - private final TransitionListener mTransitionListener = new TransitionListener() { - @Override - public void onTransitionStart(Transition transition) { - mEnterTransitionRunning = true; - } + private final TransitionListener mTransitionListener = + new TransitionListener() { + @Override + public void onTransitionStart(Transition transition) { + mEnterTransitionRunning = true; + } - @Override - public void onTransitionEnd(Transition transition) { - mEnterTransitionRunning = false; - onEnterTransitionEnd(); - } + @Override + public void onTransitionEnd(Transition transition) { + mEnterTransitionRunning = false; + onEnterTransitionEnd(); + } - @Override - public void onTransitionCancel(Transition transition) { } + @Override + public void onTransitionCancel(Transition transition) {} - @Override - public void onTransitionPause(Transition transition) { } + @Override + public void onTransitionPause(Transition transition) {} - @Override - public void onTransitionResume(Transition transition) { } - }; + @Override + public void onTransitionResume(Transition transition) {} + }; - /** - * Returns {@code true} if the enter/reenter transition is running. - */ + /** Returns {@code true} if the enter/reenter transition is running. */ protected boolean isEnterTransitionRunning() { return mEnterTransitionRunning; } - /** - * Called when the enter/reenter transition ends. - */ - protected void onEnterTransitionEnd() { } + /** Called when the enter/reenter transition ends. */ + protected void onEnterTransitionEnd() {} public SetupFragment() { setAllowEnterTransitionOverlap(false); setAllowReturnTransitionOverlap(false); - enableFragmentTransition(FRAGMENT_ENTER_TRANSITION | FRAGMENT_EXIT_TRANSITION - | FRAGMENT_REENTER_TRANSITION | FRAGMENT_RETURN_TRANSITION); + enableFragmentTransition( + FRAGMENT_ENTER_TRANSITION + | FRAGMENT_EXIT_TRANSITION + | FRAGMENT_REENTER_TRANSITION + | FRAGMENT_RETURN_TRANSITION); } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(getLayoutResourceId(), container, false); // After the transition animation, we need to request the focus. If not, this fragment // doesn't have the focus. @@ -100,18 +103,17 @@ public abstract class SetupFragment extends Fragment { return view; } - /** - * Returns the layout resource ID for this fragment. - */ - abstract protected int getLayoutResourceId(); + /** Returns the layout resource ID for this fragment. */ + protected abstract int getLayoutResourceId(); protected void setOnClickAction(View view, final String category, final int actionId) { - view.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - onActionClick(category, actionId); - } - }); + view.setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View view) { + onActionClick(category, actionId); + } + }); } protected boolean onActionClick(String category, int actionId) { @@ -141,24 +143,22 @@ public abstract class SetupFragment extends Fragment { /** * Enables fragment transition according to the given {@code mask}. * - * @param mask This value is the combination of {@link #FRAGMENT_ENTER_TRANSITION}, - * {@link #FRAGMENT_EXIT_TRANSITION}, {@link #FRAGMENT_REENTER_TRANSITION}, and - * {@link #FRAGMENT_RETURN_TRANSITION}. + * @param mask This value is the combination of {@link #FRAGMENT_ENTER_TRANSITION}, {@link + * #FRAGMENT_EXIT_TRANSITION}, {@link #FRAGMENT_REENTER_TRANSITION}, and {@link + * #FRAGMENT_RETURN_TRANSITION}. */ public void enableFragmentTransition(@FragmentTransitionType int mask) { - setEnterTransition((mask & FRAGMENT_ENTER_TRANSITION) == 0 ? null - : createTransition(Gravity.END)); - setExitTransition((mask & FRAGMENT_EXIT_TRANSITION) == 0 ? null - : createTransition(Gravity.START)); - setReenterTransition((mask & FRAGMENT_REENTER_TRANSITION) == 0 ? null - : createTransition(Gravity.START)); - setReturnTransition((mask & FRAGMENT_RETURN_TRANSITION) == 0 ? null - : createTransition(Gravity.END)); + setEnterTransition( + (mask & FRAGMENT_ENTER_TRANSITION) == 0 ? null : createTransition(Gravity.END)); + setExitTransition( + (mask & FRAGMENT_EXIT_TRANSITION) == 0 ? null : createTransition(Gravity.START)); + setReenterTransition( + (mask & FRAGMENT_REENTER_TRANSITION) == 0 ? null : createTransition(Gravity.START)); + setReturnTransition( + (mask & FRAGMENT_RETURN_TRANSITION) == 0 ? null : createTransition(Gravity.END)); } - /** - * Sets the transition with the given {@code slidEdge}. - */ + /** Sets the transition with the given {@code slidEdge}. */ public void setFragmentTransition(@FragmentTransitionType int transitionType, int slideEdge) { switch (transitionType) { case FRAGMENT_ENTER_TRANSITION: @@ -184,9 +184,7 @@ public abstract class SetupFragment extends Fragment { .build(); } - /** - * Changes the move distance of the transitions to short distance. - */ + /** Changes the move distance of the transitions to short distance. */ public void setShortDistance(@FragmentTransitionType int mask) { if ((mask & FRAGMENT_ENTER_TRANSITION) != 0) { Transition transition = getEnterTransition(); @@ -218,7 +216,7 @@ public abstract class SetupFragment extends Fragment { * Returns the ID's of the view's whose descendants will perform delayed move. * * @see com.android.tv.common.ui.setup.animation.SetupAnimationHelper.TransitionBuilder - * #setParentIdsForDelay + * #setParentIdsForDelay */ protected int[] getParentIdsForDelay() { return null; @@ -228,7 +226,7 @@ public abstract class SetupFragment extends Fragment { * Sets the ID's of the views which will not be included in the transition. * * @see com.android.tv.common.ui.setup.animation.SetupAnimationHelper.TransitionBuilder - * #setExcludeIds + * #setExcludeIds */ protected int[] getExcludedTargetIds() { return null; diff --git a/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java b/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java index 88159da9..3c76c269 100644 --- a/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java +++ b/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java @@ -16,22 +16,26 @@ package com.android.tv.common.ui.setup; +import static android.content.Context.ACCESSIBILITY_SERVICE; + import android.os.Bundle; import android.support.v17.leanback.app.GuidedStepFragment; import android.support.v17.leanback.widget.GuidanceStylist; import android.support.v17.leanback.widget.GuidedAction; +import android.support.v17.leanback.widget.GuidedActionsStylist; import android.support.v17.leanback.widget.VerticalGridView; import android.view.LayoutInflater; import android.view.View; +import android.view.View.AccessibilityDelegate; import android.view.ViewGroup; import android.view.ViewGroup.MarginLayoutParams; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.LinearLayout; - import com.android.tv.common.R; -/** - * A fragment for channel source info/setup. - */ +/** A fragment for channel source info/setup. */ public abstract class SetupGuidedStepFragment extends GuidedStepFragment { /** * Key of the argument which indicate whether the parent of this fragment has three panes. @@ -40,23 +44,32 @@ public abstract class SetupGuidedStepFragment extends GuidedStepFragment { */ public static final String KEY_THREE_PANE = "key_three_pane"; + private View mContentFragment; + private boolean mFromContentFragment; + private boolean mAccessibilityMode; + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); Bundle arguments = getArguments(); - view.findViewById(R.id.action_fragment_root).setPadding(0, 0, 0, 0); - LinearLayout.LayoutParams guidanceLayoutParams = (LinearLayout.LayoutParams) - view.findViewById(R.id.content_fragment).getLayoutParams(); + view.findViewById(android.support.v17.leanback.R.id.action_fragment_root) + .setPadding(0, 0, 0, 0); + mContentFragment = view.findViewById(android.support.v17.leanback.R.id.content_fragment); + LinearLayout.LayoutParams guidanceLayoutParams = + (LinearLayout.LayoutParams) mContentFragment.getLayoutParams(); guidanceLayoutParams.weight = 0; if (arguments != null && arguments.getBoolean(KEY_THREE_PANE, false)) { // Content fragment. - guidanceLayoutParams.width = getResources().getDimensionPixelOffset( - R.dimen.setup_guidedstep_guidance_section_width_3pane); - int doneButtonWidth = getResources().getDimensionPixelOffset( - R.dimen.setup_done_button_container_width); + guidanceLayoutParams.width = + getResources() + .getDimensionPixelOffset( + R.dimen.setup_guidedstep_guidance_section_width_3pane); + int doneButtonWidth = + getResources() + .getDimensionPixelOffset(R.dimen.setup_done_button_container_width); // Guided actions list - View list = view.findViewById(R.id.guidedactions_list); + View list = view.findViewById(android.support.v17.leanback.R.id.guidedactions_list); MarginLayoutParams marginLayoutParams = (MarginLayoutParams) list.getLayoutParams(); // Use content view to check layout direction while view is being created. if (getResources().getConfiguration().getLayoutDirection() @@ -67,31 +80,68 @@ public abstract class SetupGuidedStepFragment extends GuidedStepFragment { } } else { // Content fragment. - guidanceLayoutParams.width = getResources().getDimensionPixelOffset( - R.dimen.setup_guidedstep_guidance_section_width_2pane); + guidanceLayoutParams.width = + getResources() + .getDimensionPixelOffset( + R.dimen.setup_guidedstep_guidance_section_width_2pane); } // gridView Alignment VerticalGridView gridView = getGuidedActionsStylist().getActionsGridView(); - int offset = getResources().getDimensionPixelOffset( - R.dimen.setup_guidedactions_selector_margin_top); + int offset = + getResources() + .getDimensionPixelOffset(R.dimen.setup_guidedactions_selector_margin_top); gridView.setWindowAlignmentOffset(offset); gridView.setWindowAlignmentOffsetPercent(0); gridView.setItemAlignmentOffsetPercent(0); - ((ViewGroup) view.findViewById(R.id.guidedactions_list)).setTransitionGroup(false); + ((ViewGroup) view.findViewById(android.support.v17.leanback.R.id.guidedactions_list)) + .setTransitionGroup(false); // Needed for the shared element transition. // content_frame is defined in leanback. - ViewGroup group = (ViewGroup) view.findViewById(R.id.content_frame); + ViewGroup group = + (ViewGroup) view.findViewById(android.support.v17.leanback.R.id.content_frame); group.setClipChildren(false); group.setClipToPadding(false); return view; } @Override + public GuidedActionsStylist onCreateActionsStylist() { + return new SetupGuidedStepFragmentGuidedActionsStylist(); + } + + @Override + public void onResume() { + super.onResume(); + AccessibilityManager am = + (AccessibilityManager) getActivity().getSystemService(ACCESSIBILITY_SERVICE); + mAccessibilityMode = am != null && am.isEnabled() && am.isTouchExplorationEnabled(); + mContentFragment.setFocusable(mAccessibilityMode); + if (mAccessibilityMode) { + mContentFragment.setAccessibilityDelegate( + new AccessibilityDelegate() { + @Override + public boolean performAccessibilityAction(View host, int action, Bundle args) { + if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS + && !getActions().isEmpty()) { + // scroll to the top. This makes the first action view on the screen. + // Otherwise, the view can be recycled, so accessibility events cannot + // be sent later. + getGuidedActionsStylist().getActionsGridView().scrollToPosition(0); + mFromContentFragment = true; + } + return super.performAccessibilityAction(host, action, args); + } + }); + mContentFragment.requestFocus(); + } + } + + @Override public GuidanceStylist onCreateGuidanceStylist() { return new GuidanceStylist() { @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Guidance guidance) { + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Guidance guidance) { View view = super.onCreateView(inflater, container, guidance); if (guidance.getIconDrawable() == null) { // Icon view should not take up space when we don't use image. @@ -102,10 +152,19 @@ public abstract class SetupGuidedStepFragment extends GuidedStepFragment { }; } - abstract protected String getActionCategory(); + protected abstract String getActionCategory(); + + protected View getDoneButton() { + return getActivity().findViewById(R.id.button_done); + } @Override public void onGuidedActionClicked(GuidedAction action) { + if (!action.isFocusable()) { + // an unfocusable action may be clicked in accessibility mode when it's accessibility + // focused + return; + } SetupActionHelper.onActionClick(this, getActionCategory(), (int) action.getId()); } @@ -118,4 +177,38 @@ public abstract class SetupGuidedStepFragment extends GuidedStepFragment { public boolean isFocusOutEndAllowed() { return true; } + + protected void setAccessibilityDelegate(GuidedActionsStylist.ViewHolder vh, + GuidedAction action) { + if (!mAccessibilityMode || findActionPositionById(action.getId()) == 0) { + return; + } + vh.itemView.setAccessibilityDelegate( + new AccessibilityDelegate() { + @Override + public boolean performAccessibilityAction(View host, int action, Bundle args) { + if ((action == AccessibilityNodeInfo.ACTION_FOCUS + || action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) + && mFromContentFragment) { + // block the action and make the first action view accessibility focused + View view = getActionItemView(0); + if (view != null) { + view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + mFromContentFragment = false; + return true; + } + } + return super.performAccessibilityAction(host, action, args); + } + }); + } + + private class SetupGuidedStepFragmentGuidedActionsStylist extends GuidedActionsStylist { + + @Override + public void onBindViewHolder(GuidedActionsStylist.ViewHolder vh, GuidedAction action) { + super.onBindViewHolder(vh, action); + setAccessibilityDelegate(vh, action); + } + } } diff --git a/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java b/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java index b9ad4657..c02d3f56 100644 --- a/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java +++ b/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java @@ -23,34 +23,43 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.MarginLayoutParams; - import com.android.tv.common.R; -/** - * A fragment for channel source info/setup. - */ +/** A fragment for channel source info/setup. */ public abstract class SetupMultiPaneFragment extends SetupFragment { private static final String TAG = "SetupMultiPaneFragment"; private static final boolean DEBUG = false; public static final int ACTION_DONE = Integer.MAX_VALUE; public static final int ACTION_SKIP = ACTION_DONE - 1; + public static final int MAX_SUBCLASSES_ID = ACTION_SKIP - 1; - private static final String CONTENT_FRAGMENT_TAG = "content_fragment"; + public static final String CONTENT_FRAGMENT_TAG = "content_fragment"; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (DEBUG) { - Log.d(TAG, "onCreateView(" + inflater + ", " + container + ", " + savedInstanceState - + ")"); + Log.d( + TAG, + "onCreateView(" + + inflater + + ", " + + container + + ", " + + savedInstanceState + + ")"); } View view = super.onCreateView(inflater, container, savedInstanceState); if (savedInstanceState == null) { SetupGuidedStepFragment contentFragment = onCreateContentFragment(); - getChildFragmentManager().beginTransaction() - .replace(R.id.guided_step_fragment_container, contentFragment, - CONTENT_FRAGMENT_TAG).commit(); + getChildFragmentManager() + .beginTransaction() + .replace( + R.id.guided_step_fragment_container, + contentFragment, + CONTENT_FRAGMENT_TAG) + .commit(); } if (needsDoneButton()) { setOnClickAction(view.findViewById(R.id.button_done), getActionCategory(), ACTION_DONE); @@ -65,12 +74,12 @@ public abstract class SetupMultiPaneFragment extends SetupFragment { if (getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) { ((MarginLayoutParams) doneButtonContainer.getLayoutParams()).rightMargin = - -getResources().getDimensionPixelOffset( - R.dimen.setup_done_button_container_width); + -getResources() + .getDimensionPixelOffset(R.dimen.setup_done_button_container_width); } else { ((MarginLayoutParams) doneButtonContainer.getLayoutParams()).leftMargin = - -getResources().getDimensionPixelOffset( - R.dimen.setup_done_button_container_width); + -getResources() + .getDimensionPixelOffset(R.dimen.setup_done_button_container_width); } view.findViewById(R.id.button_done).setFocusable(false); } @@ -82,15 +91,15 @@ public abstract class SetupMultiPaneFragment extends SetupFragment { return R.layout.fragment_setup_multi_pane; } - abstract protected SetupGuidedStepFragment onCreateContentFragment(); + protected abstract SetupGuidedStepFragment onCreateContentFragment(); @Nullable protected SetupGuidedStepFragment getContentFragment() { - return (SetupGuidedStepFragment) getChildFragmentManager() - .findFragmentByTag(CONTENT_FRAGMENT_TAG); + return (SetupGuidedStepFragment) + getChildFragmentManager().findFragmentByTag(CONTENT_FRAGMENT_TAG); } - abstract protected String getActionCategory(); + protected abstract String getActionCategory(); protected boolean needsDoneButton() { return true; @@ -102,11 +111,16 @@ public abstract class SetupMultiPaneFragment extends SetupFragment { @Override protected int[] getParentIdsForDelay() { - return new int[] {R.id.content_fragment, R.id.guidedactions_list}; + return new int[] { + android.support.v17.leanback.R.id.content_fragment, + android.support.v17.leanback.R.id.guidedactions_list + }; } @Override public int[] getSharedElementIds() { - return new int[] {R.id.action_fragment_background, R.id.done_button_container}; + return new int[] { + android.support.v17.leanback.R.id.action_fragment_background, R.id.done_button_container + }; } -}
\ No newline at end of file +} diff --git a/common/src/com/android/tv/common/ui/setup/animation/FadeAndShortSlide.java b/common/src/com/android/tv/common/ui/setup/animation/FadeAndShortSlide.java index e1a8e60c..60ffb70f 100644 --- a/common/src/com/android/tv/common/ui/setup/animation/FadeAndShortSlide.java +++ b/common/src/com/android/tv/common/ui/setup/animation/FadeAndShortSlide.java @@ -29,15 +29,12 @@ import android.view.ViewGroup; import android.view.ViewParent; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; - import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; -/** - * Execute horizontal slide of 1/4 width and fade (to workaround bug 23718734) - */ +/** Execute horizontal slide of 1/4 width and fade (to workaround bug 23718734) */ public class FadeAndShortSlide extends Visibility { private static final TimeInterpolator APPEAR_INTERPOLATOR = new DecelerateInterpolator(); private static final TimeInterpolator DISAPPEAR_INTERPOLATOR = new AccelerateInterpolator(); @@ -48,39 +45,45 @@ public class FadeAndShortSlide extends Visibility { private static final int DEFAULT_DISTANCE = 200; - private static abstract class CalculateSlide { + private abstract static class CalculateSlide { /** Returns the translation value for view when it goes out of the scene */ - public abstract float getGoneX(ViewGroup sceneRoot, View view, int[] position, - int distance); + public abstract float getGoneX( + ViewGroup sceneRoot, View view, int[] position, int distance); } - private static final CalculateSlide sCalculateStart = new CalculateSlide() { - @Override - public float getGoneX(ViewGroup sceneRoot, View view, int[] position, int distance) { - final boolean isRtl = sceneRoot.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; - final float x; - if (isRtl) { - x = view.getTranslationX() + distance; - } else { - x = view.getTranslationX() - distance; - } - return x; - } - }; - - private static final CalculateSlide sCalculateEnd = new CalculateSlide() { - @Override - public float getGoneX(ViewGroup sceneRoot, View view, int[] position, int distance) { - final boolean isRtl = sceneRoot.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; - final float x; - if (isRtl) { - x = view.getTranslationX() - distance; - } else { - x = view.getTranslationX() + distance; - } - return x; - } - }; + private static final CalculateSlide sCalculateStart = + new CalculateSlide() { + @Override + public float getGoneX( + ViewGroup sceneRoot, View view, int[] position, int distance) { + final boolean isRtl = + sceneRoot.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + final float x; + if (isRtl) { + x = view.getTranslationX() + distance; + } else { + x = view.getTranslationX() - distance; + } + return x; + } + }; + + private static final CalculateSlide sCalculateEnd = + new CalculateSlide() { + @Override + public float getGoneX( + ViewGroup sceneRoot, View view, int[] position, int distance) { + final boolean isRtl = + sceneRoot.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + final float x; + if (isRtl) { + x = view.getTranslationX() - distance; + } else { + x = view.getTranslationX() + distance; + } + return x; + } + }; private static final ViewPositionComparator sViewPositionComparator = new ViewPositionComparator(); @@ -131,9 +134,10 @@ public class FadeAndShortSlide extends Visibility { getTransitionTargets((ViewGroup) parentForDelay, transitionTargets); sViewPositionComparator.mParentForDelay = parentForDelay; sViewPositionComparator.mIsLtr = view.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR; - sViewPositionComparator.mToLeft = sViewPositionComparator.mIsLtr - ? mSlideEdge == (appear ? Gravity.END : Gravity.START) - : mSlideEdge == (appear ? Gravity.START : Gravity.END); + sViewPositionComparator.mToLeft = + sViewPositionComparator.mIsLtr + ? mSlideEdge == (appear ? Gravity.END : Gravity.START) + : mSlideEdge == (appear ? Gravity.START : Gravity.END); Collections.sort(transitionTargets, sViewPositionComparator); return transitionTargets.indexOf(view); } @@ -180,8 +184,8 @@ public class FadeAndShortSlide extends Visibility { captureValues(transitionValues); int delayIndex = getDelayOrder(transitionValues.view, false); if (delayIndex > 0) { - transitionValues.values.put(PROPNAME_DELAY, - delayIndex * SetupAnimationHelper.DELAY_BETWEEN_SIBLINGS_MS); + transitionValues.values.put( + PROPNAME_DELAY, delayIndex * SetupAnimationHelper.DELAY_BETWEEN_SIBLINGS_MS); } } @@ -192,8 +196,8 @@ public class FadeAndShortSlide extends Visibility { captureValues(transitionValues); int delayIndex = getDelayOrder(transitionValues.view, true); if (delayIndex > 0) { - transitionValues.values.put(PROPNAME_DELAY, - delayIndex * SetupAnimationHelper.DELAY_BETWEEN_SIBLINGS_MS); + transitionValues.values.put( + PROPNAME_DELAY, delayIndex * SetupAnimationHelper.DELAY_BETWEEN_SIBLINGS_MS); } } @@ -212,7 +216,10 @@ public class FadeAndShortSlide extends Visibility { } @Override - public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, + public Animator onAppear( + ViewGroup sceneRoot, + View view, + TransitionValues startValues, TransitionValues endValues) { if (endValues == null) { return null; @@ -221,15 +228,16 @@ public class FadeAndShortSlide extends Visibility { int left = position[0]; float endX = view.getTranslationX(); float startX = mSlideCalculator.getGoneX(sceneRoot, view, position, mDistance); - final Animator slideAnimator = TranslationAnimationCreator.createAnimation(view, endValues, - left, startX, endX, APPEAR_INTERPOLATOR, this); + final Animator slideAnimator = + TranslationAnimationCreator.createAnimation( + view, endValues, left, startX, endX, APPEAR_INTERPOLATOR, this); if (slideAnimator == null) { return null; } mFade.setInterpolator(APPEAR_INTERPOLATOR); final AnimatorSet set = new AnimatorSet(); set.play(slideAnimator).with(mFade.onAppear(sceneRoot, view, startValues, endValues)); - Long delay = (Long ) endValues.values.get(PROPNAME_DELAY); + Long delay = (Long) endValues.values.get(PROPNAME_DELAY); if (delay != null) { set.setStartDelay(delay); } @@ -237,7 +245,10 @@ public class FadeAndShortSlide extends Visibility { } @Override - public Animator onDisappear(ViewGroup sceneRoot, final View view, TransitionValues startValues, + public Animator onDisappear( + ViewGroup sceneRoot, + final View view, + TransitionValues startValues, TransitionValues endValues) { if (startValues == null) { return null; @@ -246,8 +257,9 @@ public class FadeAndShortSlide extends Visibility { int left = position[0]; float startX = view.getTranslationX(); float endX = mSlideCalculator.getGoneX(sceneRoot, view, position, mDistance); - final Animator slideAnimator = TranslationAnimationCreator.createAnimation(view, - startValues, left, startX, endX, DISAPPEAR_INTERPOLATOR, this); + final Animator slideAnimator = + TranslationAnimationCreator.createAnimation( + view, startValues, left, startX, endX, DISAPPEAR_INTERPOLATOR, this); if (slideAnimator == null) { // slideAnimator is null if startX == endX return null; } @@ -257,13 +269,14 @@ public class FadeAndShortSlide extends Visibility { if (fadeAnimator == null) { return null; } - fadeAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animator) { - fadeAnimator.removeListener(this); - view.setAlpha(0.0f); - } - }); + fadeAnimator.addListener( + new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animator) { + fadeAnimator.removeListener(this); + view.setAlpha(0.0f); + } + }); final AnimatorSet set = new AnimatorSet(); set.play(slideAnimator).with(fadeAnimator); @@ -300,9 +313,7 @@ public class FadeAndShortSlide extends Visibility { return super.setDuration(scaledDuration); } - /** - * Sets the moving distance in pixel. - */ + /** Sets the moving distance in pixel. */ public void setDistance(int distance) { mDistance = distance; } diff --git a/common/src/com/android/tv/common/ui/setup/animation/SetupAnimationHelper.java b/common/src/com/android/tv/common/ui/setup/animation/SetupAnimationHelper.java index d98138a2..2a913c6e 100644 --- a/common/src/com/android/tv/common/ui/setup/animation/SetupAnimationHelper.java +++ b/common/src/com/android/tv/common/ui/setup/animation/SetupAnimationHelper.java @@ -27,12 +27,9 @@ import android.transition.TransitionSet; import android.view.Gravity; import android.view.View; import android.widget.ImageView; - import com.android.tv.common.R; -/** - * A helper class for setup animation. - */ +/** A helper class for setup animation. */ public final class SetupAnimationHelper { public static final long DELAY_BETWEEN_SIBLINGS_MS = applyAnimationTimeScale(33); @@ -43,21 +40,21 @@ public final class SetupAnimationHelper { private static int sFragmentTransitionLongDistance; private static int sFragmentTransitionShortDistance; - private SetupAnimationHelper() { } + private SetupAnimationHelper() {} - /** - * Load initial parameters. This method should be called before using this class. - */ + /** Load initial parameters. This method should be called before using this class. */ public static void initialize(Context context) { if (sInitialized) { return; } - sFragmentTransitionDuration = context.getResources() - .getInteger(R.integer.setup_fragment_transition_duration); - sFragmentTransitionLongDistance = context.getResources() - .getDimensionPixelOffset(R.dimen.setup_fragment_transition_long_distance); - sFragmentTransitionShortDistance = context.getResources() - .getDimensionPixelOffset(R.dimen.setup_fragment_transition_short_distance); + sFragmentTransitionDuration = + context.getResources().getInteger(R.integer.setup_fragment_transition_duration); + sFragmentTransitionLongDistance = + context.getResources() + .getDimensionPixelOffset(R.dimen.setup_fragment_transition_long_distance); + sFragmentTransitionShortDistance = + context.getResources() + .getDimensionPixelOffset(R.dimen.setup_fragment_transition_short_distance); sInitialized = true; } @@ -88,9 +85,7 @@ public final class SetupAnimationHelper { return this; } - /** - * Sets the duration of the transition. - */ + /** Sets the duration of the transition. */ public TransitionBuilder setDuration(long duration) { mDuration = duration; return this; @@ -106,17 +101,13 @@ public final class SetupAnimationHelper { return this; } - /** - * Sets the ID's of the views which will not be included in the transition. - */ + /** Sets the ID's of the views which will not be included in the transition. */ public TransitionBuilder setExcludeIds(int[] excludeIds) { mExcludeIds = excludeIds; return this; } - /** - * Builds and returns the {@link android.transition.Transition}. - */ + /** Builds and returns the {@link android.transition.Transition}. */ public Transition build() { FadeAndShortSlide transition = new FadeAndShortSlide(mSlideEdge, mParentIdForDelay); transition.setDistance(mDistance); @@ -130,25 +121,19 @@ public final class SetupAnimationHelper { } } - /** - * Changes the move distance of the {@code transition} to long distance. - */ + /** Changes the move distance of the {@code transition} to long distance. */ public static void setLongDistance(FadeAndShortSlide transition) { checkInitialized(); transition.setDistance(sFragmentTransitionLongDistance); } - /** - * Changes the move distance of the {@code transition} to short distance. - */ + /** Changes the move distance of the {@code transition} to short distance. */ public static void setShortDistance(FadeAndShortSlide transition) { checkInitialized(); transition.setDistance(sFragmentTransitionShortDistance); } - /** - * Applies the animation scale to the given {@code animator}. - */ + /** Applies the animation scale to the given {@code animator}. */ public static Animator applyAnimationTimeScale(Animator animator) { if (animator instanceof AnimatorSet) { for (Animator child : ((AnimatorSet) animator).getChildAnimations()) { @@ -162,9 +147,7 @@ public final class SetupAnimationHelper { return animator; } - /** - * Applies the animation scale to the given {@code transition}. - */ + /** Applies the animation scale to the given {@code transition}. */ public static Transition applyAnimationTimeScale(Transition transition) { if (transition instanceof TransitionSet) { TransitionSet set = (TransitionSet) transition; @@ -180,9 +163,7 @@ public final class SetupAnimationHelper { return transition; } - /** - * Applies the animation scale to the given {@code time}. - */ + /** Applies the animation scale to the given {@code time}. */ public static long applyAnimationTimeScale(long time) { return (long) (time * ANIMATION_TIME_SCALE); } @@ -197,23 +178,25 @@ public final class SetupAnimationHelper { } /** - * Returns an animator which animates the source image of the {@link ImageView} with start delay. + * Returns an animator which animates the source image of the {@link ImageView} with start + * delay. * * <p>The frame rate is 60 fps. */ - public static ObjectAnimator createFrameAnimatorWithDelay(ImageView imageView, int[] frames, - long startDelay) { + public static ObjectAnimator createFrameAnimatorWithDelay( + ImageView imageView, int[] frames, long startDelay) { ObjectAnimator animator = ObjectAnimator.ofInt(imageView, "imageResource", frames); // Make it 60 fps. animator.setDuration(frames.length * 1000 / 60); animator.setInterpolator(null); animator.setStartDelay(startDelay); - animator.setEvaluator(new TypeEvaluator<Integer>() { - @Override - public Integer evaluate(float fraction, Integer startValue, Integer endValue) { - return startValue; - } - }); + animator.setEvaluator( + new TypeEvaluator<Integer>() { + @Override + public Integer evaluate(float fraction, Integer startValue, Integer endValue) { + return startValue; + } + }); return animator; } @@ -223,19 +206,20 @@ public final class SetupAnimationHelper { * @param view The view which will be animated. * @param duration The duration of the animation. * @param makeVisibleAfterAnimation If {@code true}, the view will become visible after the - * animation ends. + * animation ends. */ - public static Animator createFadeOutAnimator(final View view, long duration, - boolean makeVisibleAfterAnimation) { + public static Animator createFadeOutAnimator( + final View view, long duration, boolean makeVisibleAfterAnimation) { ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.ALPHA, 1.0f, 0.0f).setDuration(duration); if (makeVisibleAfterAnimation) { - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - view.setAlpha(1.0f); - } - }); + animator.addListener( + new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + view.setAlpha(1.0f); + } + }); } return animator; } diff --git a/common/src/com/android/tv/common/ui/setup/animation/TranslationAnimationCreator.java b/common/src/com/android/tv/common/ui/setup/animation/TranslationAnimationCreator.java index 99b8811a..13b89ea1 100644 --- a/common/src/com/android/tv/common/ui/setup/animation/TranslationAnimationCreator.java +++ b/common/src/com/android/tv/common/ui/setup/animation/TranslationAnimationCreator.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2017 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 com.android.tv.common.ui.setup.animation; import android.animation.Animator; @@ -5,18 +20,16 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.graphics.Path; +import android.support.v17.leanback.R; import android.transition.Transition; import android.transition.TransitionValues; import android.view.View; -import com.android.tv.common.R; - /** * This class is used by Slide and Explode to create an animator that goes from the start position * to the end position. It takes into account the canceled position so that it will not blink out or - * shift suddenly when the transition is interrupted. - * The original class is android.support.v17.leanback.transition.TranslationAnimationCreator which - * is hidden. + * shift suddenly when the transition is interrupted. The original class is + * android.support.v17.leanback.transition.TranslationAnimationCreator which is hidden. */ // Copied from android.support.v17.leanback.transition.TransltaionAnimationCreator class TranslationAnimationCreator { @@ -31,11 +44,16 @@ class TranslationAnimationCreator { * @param endX The end translation x of view * @param interpolator The interpolator to use with this animator. * @return An animator that moves from (startX, startY) to (endX, endY) unless there was a - * previous interruption, in which case it moves from the current position to (endX, - * endY). + * previous interruption, in which case it moves from the current position to (endX, endY). */ - static Animator createAnimation(View view, TransitionValues values, int viewPosX, float startX, - float endX, TimeInterpolator interpolator, Transition transition) { + static Animator createAnimation( + View view, + TransitionValues values, + int viewPosX, + float startX, + float endX, + TimeInterpolator interpolator, + Transition transition) { float terminalX = view.getTranslationX(); Integer startPosition = (Integer) values.view.getTag(R.id.transitionPosition); if (startPosition != null) { @@ -74,8 +92,8 @@ class TranslationAnimationCreator { private float mPausedX; private final float mTerminalX; - private TransitionPositionListener(View movingView, View viewInHierarchy, int startX, - float terminalX) { + private TransitionPositionListener( + View movingView, View viewInHierarchy, int startX, float terminalX) { mMovingView = movingView; mViewInHierarchy = viewInHierarchy; mStartX = startX - Math.round(mMovingView.getTranslationX()); @@ -123,6 +141,4 @@ class TranslationAnimationCreator { @Override public void onTransitionResume(Transition transition) {} } - } - |