1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tv.settings.util;
18 
19 import android.view.LayoutInflater;
20 import android.view.View;
21 import android.view.ViewGroup;
22 
23 import androidx.leanback.app.GuidedStepFragment;
24 import androidx.leanback.widget.BaseGridView;
25 import androidx.leanback.widget.FacetProvider;
26 import androidx.leanback.widget.GuidanceStylist;
27 import androidx.leanback.widget.GuidedActionsStylist;
28 import androidx.leanback.widget.ItemAlignmentFacet;
29 import androidx.leanback.widget.ItemAlignmentFacet.ItemAlignmentDef;
30 import androidx.leanback.widget.VerticalGridView;
31 
32 import com.android.tv.settings.R;
33 
34 
35 /**
36  * Utilities to align the ActionGridView so that the baseline of the title view matches with
37  * the keyline of the fragment.
38  */
39 public class GuidedActionsAlignUtil {
40 
41     /**
42      * As we want to align to the mean line of the text view, we should always provide a customized
43      * viewholder with the new facet when we are creating a GuidedActionStylist.
44      */
45     private static class SetupViewHolder extends GuidedActionsStylist.ViewHolder implements
46                 FacetProvider {
SetupViewHolder(View v)47         SetupViewHolder(View v) {
48             super(v);
49         }
50 
51         // Provide a customized ItemAlignmentFacet so that the mean line of textView is matched.
52         // Here we use mean line of the textview to work as the baseline to be matched with
53         // guidance title baseline.
54         @Override
getFacet(Class facet)55         public Object getFacet(Class facet) {
56             if (facet.equals(ItemAlignmentFacet.class)) {
57                 ItemAlignmentFacet.ItemAlignmentDef alignedDef =
58                         new ItemAlignmentFacet.ItemAlignmentDef();
59                 alignedDef.setItemAlignmentViewId(
60                         androidx.leanback.R.id.guidedactions_item_title);
61                 alignedDef.setAlignedToTextViewBaseline(false);
62                 alignedDef.setItemAlignmentOffset(0);
63                 alignedDef.setItemAlignmentOffsetWithPadding(true);
64                 // 50 refers to 50 percent, which refers to mid position of textView.
65                 alignedDef.setItemAlignmentOffsetPercent(50);
66                 ItemAlignmentFacet f = new ItemAlignmentFacet();
67                 f.setAlignmentDefs(new ItemAlignmentDef[] {alignedDef});
68                 return f;
69             }
70             return null;
71         }
72     }
73 
74     /**
75      * Create a customized GuidedActionsStylist for {@link GuidedStepFragment} used in device name
76      * setup.
77      */
createGuidedActionsStylist()78     public static GuidedActionsStylist createGuidedActionsStylist() {
79         return new GuidedActionsStylist() {
80             @Override
81             public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
82                 LayoutInflater inflater = LayoutInflater.from(parent.getContext());
83                 View v = inflater.inflate(onProvideItemLayoutId(viewType), parent, false);
84                 return new GuidedActionsAlignUtil.SetupViewHolder(v);
85             }
86         };
87     }
88 
89     /**
90      * Create a customized GuidedActionsStylist {@link GuidedStepFragment} WITHOUT background used
91      * in device name customization input step.
92      */
93     public static GuidedActionsStylist createNoBackgroundGuidedActionsStylist() {
94         return new GuidedActionsStylist() {
95             @Override
96             public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
97                 LayoutInflater inflater = LayoutInflater.from(parent.getContext());
98                 View v = inflater.inflate(onProvideItemLayoutId(viewType), parent, false);
99                 v.setBackground(null);
100                 return new GuidedActionsAlignUtil.SetupViewHolder(v);
101             }
102             @Override
103             public int onProvideItemLayoutId() {
104                 return R.layout.device_name_input_item;
105             }
106         };
107     }
108 
109     /**
110      * Create a customized view for {@link androidx.leanback.app.GuidedStepFragment} used
111      * in device name setup.
112      */
113     public static View createView(View view, GuidedStepFragment guidedStepFragment) {
114         // action_fragment_root's padding cannot be set via attributes so we do it programmatically.
115         final View actionFragmentRoot = view.findViewById(R.id.action_fragment_root);
116         if (actionFragmentRoot != null) {
117             actionFragmentRoot.setPadding(0, 0, 0, 0);
118         }
119 
120         final VerticalGridView gridView = guidedStepFragment.getGuidedActionsStylist()
121                 .getActionsGridView();
122         gridView.setItemSpacing(
123                 guidedStepFragment.getResources()
124                         .getDimensionPixelSize(R.dimen.setup_list_item_margin));
125 
126         // Make the key line match with the item baseline. For our case, the item baseline is
127         // customized to be the mean line of title text view.
128         gridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_HIGH_EDGE);
129         gridView.setWindowAlignmentPreferKeyLineOverHighEdge(true);
130         return view;
131     }
132 
133     /**
134      * Create a customized GuidanceStylist for {@link GuidedStepFragment} used in device name setup.
135      */
136     public static GuidanceStylist createGuidanceStylist() {
137         return new GuidanceStylist() {
138             @Override
139             public int onProvideLayoutId() {
140                 return R.layout.device_name_content;
141             }
142         };
143     }
144 
145 }
146