1 /*
2  * Copyright (C) 2015 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.setupwizardlib;
18 
19 import android.content.Context;
20 import android.graphics.drawable.Drawable;
21 import androidx.recyclerview.widget.RecyclerView;
22 import androidx.recyclerview.widget.RecyclerView.Adapter;
23 import androidx.recyclerview.widget.RecyclerView.ViewHolder;
24 import android.util.AttributeSet;
25 import android.view.LayoutInflater;
26 import android.view.View;
27 import android.view.ViewGroup;
28 import com.android.setupwizardlib.template.RecyclerMixin;
29 import com.android.setupwizardlib.template.RecyclerViewScrollHandlingDelegate;
30 import com.android.setupwizardlib.template.RequireScrollMixin;
31 
32 /**
33  * A setup wizard layout for use with {@link androidx.recyclerview.widget.RecyclerView}. {@code
34  * android:entries} can also be used to specify an {@link
35  * com.android.setupwizardlib.items.ItemHierarchy} to be used with this layout in XML.
36  *
37  * @see SetupWizardListLayout
38  */
39 public class SetupWizardRecyclerLayout extends SetupWizardLayout {
40 
41   protected RecyclerMixin mRecyclerMixin;
42 
SetupWizardRecyclerLayout(Context context)43   public SetupWizardRecyclerLayout(Context context) {
44     this(context, 0, 0);
45   }
46 
SetupWizardRecyclerLayout(Context context, int template, int containerId)47   public SetupWizardRecyclerLayout(Context context, int template, int containerId) {
48     super(context, template, containerId);
49     init(null, 0);
50   }
51 
SetupWizardRecyclerLayout(Context context, AttributeSet attrs)52   public SetupWizardRecyclerLayout(Context context, AttributeSet attrs) {
53     super(context, attrs);
54     init(attrs, 0);
55   }
56 
SetupWizardRecyclerLayout(Context context, AttributeSet attrs, int defStyleAttr)57   public SetupWizardRecyclerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
58     super(context, attrs, defStyleAttr);
59     init(attrs, defStyleAttr);
60   }
61 
init(AttributeSet attrs, int defStyleAttr)62   private void init(AttributeSet attrs, int defStyleAttr) {
63     mRecyclerMixin.parseAttributes(attrs, defStyleAttr);
64     registerMixin(RecyclerMixin.class, mRecyclerMixin);
65 
66     final RequireScrollMixin requireScrollMixin = getMixin(RequireScrollMixin.class);
67     requireScrollMixin.setScrollHandlingDelegate(
68         new RecyclerViewScrollHandlingDelegate(requireScrollMixin, getRecyclerView()));
69   }
70 
71   @Override
onLayout(boolean changed, int left, int top, int right, int bottom)72   protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
73     super.onLayout(changed, left, top, right, bottom);
74     mRecyclerMixin.onLayout();
75   }
76 
77   /** @see RecyclerMixin#getAdapter() */
getAdapter()78   public Adapter<? extends ViewHolder> getAdapter() {
79     return mRecyclerMixin.getAdapter();
80   }
81 
82   /** @see RecyclerMixin#setAdapter(Adapter) */
setAdapter(Adapter<? extends ViewHolder> adapter)83   public void setAdapter(Adapter<? extends ViewHolder> adapter) {
84     mRecyclerMixin.setAdapter(adapter);
85   }
86 
87   /** @see RecyclerMixin#getRecyclerView() */
getRecyclerView()88   public RecyclerView getRecyclerView() {
89     return mRecyclerMixin.getRecyclerView();
90   }
91 
92   @Override
findContainer(int containerId)93   protected ViewGroup findContainer(int containerId) {
94     if (containerId == 0) {
95       containerId = R.id.suw_recycler_view;
96     }
97     return super.findContainer(containerId);
98   }
99 
100   @Override
onInflateTemplate(LayoutInflater inflater, int template)101   protected View onInflateTemplate(LayoutInflater inflater, int template) {
102     if (template == 0) {
103       template = R.layout.suw_recycler_template;
104     }
105     return super.onInflateTemplate(inflater, template);
106   }
107 
108   @Override
onTemplateInflated()109   protected void onTemplateInflated() {
110     final View recyclerView = findViewById(R.id.suw_recycler_view);
111     if (recyclerView instanceof RecyclerView) {
112       mRecyclerMixin = new RecyclerMixin(this, (RecyclerView) recyclerView);
113     } else {
114       throw new IllegalStateException(
115           "SetupWizardRecyclerLayout should use a template with recycler view");
116     }
117   }
118 
119   @Override
120   // Returning generic type is the common pattern used for findViewBy* methods
121   @SuppressWarnings("TypeParameterUnusedInFormals")
findManagedViewById(int id)122   public <T extends View> T findManagedViewById(int id) {
123     final View header = mRecyclerMixin.getHeader();
124     if (header != null) {
125       final T view = header.findViewById(id);
126       if (view != null) {
127         return view;
128       }
129     }
130     return super.findViewById(id);
131   }
132 
133   /** @deprecated Use {@link #setDividerInsets(int, int)} instead. */
134   @Deprecated
setDividerInset(int inset)135   public void setDividerInset(int inset) {
136     mRecyclerMixin.setDividerInset(inset);
137   }
138 
139   /**
140    * Sets the start inset of the divider. This will use the default divider drawable set in the
141    * theme and apply insets to it.
142    *
143    * @param start The number of pixels to inset on the "start" side of the list divider. Typically
144    *     this will be either {@code @dimen/suw_items_icon_divider_inset} or
145    *     {@code @dimen/suw_items_text_divider_inset}.
146    * @param end The number of pixels to inset on the "end" side of the list divider.
147    * @see RecyclerMixin#setDividerInsets(int, int)
148    */
setDividerInsets(int start, int end)149   public void setDividerInsets(int start, int end) {
150     mRecyclerMixin.setDividerInsets(start, end);
151   }
152 
153   /** @deprecated Use {@link #getDividerInsetStart()} instead. */
154   @Deprecated
getDividerInset()155   public int getDividerInset() {
156     return mRecyclerMixin.getDividerInset();
157   }
158 
159   /** @see RecyclerMixin#getDividerInsetStart() */
getDividerInsetStart()160   public int getDividerInsetStart() {
161     return mRecyclerMixin.getDividerInsetStart();
162   }
163 
164   /** @see RecyclerMixin#getDividerInsetEnd() */
getDividerInsetEnd()165   public int getDividerInsetEnd() {
166     return mRecyclerMixin.getDividerInsetEnd();
167   }
168 
169   /** @see RecyclerMixin#getDivider() */
getDivider()170   public Drawable getDivider() {
171     return mRecyclerMixin.getDivider();
172   }
173 }
174