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.support.v17.leanback.app.GuidedStepFragment;
20 import android.support.v17.leanback.widget.BaseGridView;
21 import android.support.v17.leanback.widget.FacetProvider;
22 import android.support.v17.leanback.widget.GuidanceStylist;
23 import android.support.v17.leanback.widget.GuidedActionsStylist;
24 import android.support.v17.leanback.widget.ItemAlignmentFacet;
25 import android.support.v17.leanback.widget.ItemAlignmentFacet.ItemAlignmentDef;
26 import android.support.v17.leanback.widget.VerticalGridView;
27 import android.view.LayoutInflater;
28 import android.view.View;
29 import android.view.ViewGroup;
30 
31 import com.android.tv.settings.R;
32 
33 
34 /**
35  * Utilities to align the ActionGridView so that the baseline of the title view matches with
36  * the keyline of the fragment.
37  */
38 public class GuidedActionsAlignUtil {
39 
40     /**
41      * As we want to align to the mean line of the text view, we should always provide a customized
42      * viewholder with the new facet when we are creating a GuidedActionStylist.
43      */
44     private static class SetupViewHolder extends GuidedActionsStylist.ViewHolder implements
45                 FacetProvider {
SetupViewHolder(View v)46         SetupViewHolder(View v) {
47             super(v);
48         }
49 
50         // Provide a customized ItemAlignmentFacet so that the mean line of textView is matched.
51         // Here we use mean line of the textview to work as the baseline to be matched with
52         // guidance title baseline.
53         @Override
getFacet(Class facet)54         public Object getFacet(Class facet) {
55             if (facet.equals(ItemAlignmentFacet.class)) {
56                 ItemAlignmentFacet.ItemAlignmentDef alignedDef =
57                         new ItemAlignmentFacet.ItemAlignmentDef();
58                 alignedDef.setItemAlignmentViewId(
59                         android.support.v17.leanback.R.id.guidedactions_item_title);
60                 alignedDef.setAlignedToTextViewBaseline(false);
61                 alignedDef.setItemAlignmentOffset(0);
62                 alignedDef.setItemAlignmentOffsetWithPadding(true);
63                 // 50 refers to 50 percent, which refers to mid position of textView.
64                 alignedDef.setItemAlignmentOffsetPercent(50);
65                 ItemAlignmentFacet f = new ItemAlignmentFacet();
66                 f.setAlignmentDefs(new ItemAlignmentDef[] {alignedDef});
67                 return f;
68             }
69             return null;
70         }
71     }
72 
73     /**
74      * Create a customized GuidedActionsStylist for {@link GuidedStepFragment} used in device name
75      * setup.
76      */
createGuidedActionsStylist()77     public static GuidedActionsStylist createGuidedActionsStylist() {
78         return new GuidedActionsStylist() {
79             @Override
80             public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
81                 LayoutInflater inflater = LayoutInflater.from(parent.getContext());
82                 View v = inflater.inflate(onProvideItemLayoutId(viewType), parent, false);
83                 return new GuidedActionsAlignUtil.SetupViewHolder(v);
84             }
85         };
86     }
87 
88     /**
89      * Create a customized GuidedActionsStylist {@link GuidedStepFragment} WITHOUT background used
90      * in device name customization input step.
91      */
92     public static GuidedActionsStylist createNoBackgroundGuidedActionsStylist() {
93         return new GuidedActionsStylist() {
94             @Override
95             public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
96                 LayoutInflater inflater = LayoutInflater.from(parent.getContext());
97                 View v = inflater.inflate(onProvideItemLayoutId(viewType), parent, false);
98                 v.setBackground(null);
99                 return new GuidedActionsAlignUtil.SetupViewHolder(v);
100             }
101         };
102     }
103 
104     /**
105      * Create a customized view for {@link android.support.v17.leanback.app.GuidedStepFragment} used
106      * in device name setup.
107      */
108     public static View createView(View view, GuidedStepFragment guidedStepFragment) {
109         // action_fragment_root's padding cannot be set via attributes so we do it programmatically.
110         final View actionFragmentRoot = view.findViewById(R.id.action_fragment_root);
111         if (actionFragmentRoot != null) {
112             actionFragmentRoot.setPadding(0, 0, 0, 0);
113         }
114 
115         final VerticalGridView gridView = guidedStepFragment.getGuidedActionsStylist()
116                 .getActionsGridView();
117         gridView.setItemSpacing(
118                 guidedStepFragment.getResources()
119                         .getDimensionPixelSize(R.dimen.setup_list_item_margin));
120 
121         // Make the key line match with the item baseline. For our case, the item baseline is
122         // customized to be the mean line of title text view.
123         gridView.setWindowAlignment(BaseGridView.WINDOW_ALIGN_HIGH_EDGE);
124         gridView.setWindowAlignmentPreferKeyLineOverHighEdge(true);
125         return view;
126     }
127 
128     /**
129      * Create a customized GuidanceStylist for {@link GuidedStepFragment} used in device name setup.
130      */
131     public static GuidanceStylist createGuidanceStylist() {
132         return new GuidanceStylist() {
133             @Override
134             public int onProvideLayoutId() {
135                 return R.layout.device_name_content;
136             }
137         };
138     }
139 
140 }
141