Home | History | Annotate | Download | only in setupwizardlib
      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.content.res.TypedArray;
     21 import android.graphics.drawable.Drawable;
     22 import android.os.Build;
     23 import android.support.v7.widget.LinearLayoutManager;
     24 import android.support.v7.widget.RecyclerView;
     25 import android.util.AttributeSet;
     26 import android.util.Log;
     27 import android.view.LayoutInflater;
     28 import android.view.View;
     29 import android.view.ViewGroup;
     30 import android.widget.TextView;
     31 
     32 import com.android.setupwizardlib.items.ItemGroup;
     33 import com.android.setupwizardlib.items.ItemInflater;
     34 import com.android.setupwizardlib.items.RecyclerItemAdapter;
     35 import com.android.setupwizardlib.util.DrawableLayoutDirectionHelper;
     36 import com.android.setupwizardlib.util.RecyclerViewRequireScrollHelper;
     37 import com.android.setupwizardlib.view.HeaderRecyclerView;
     38 import com.android.setupwizardlib.view.NavigationBar;
     39 
     40 /**
     41  * A setup wizard layout for use with {@link android.support.v7.widget.RecyclerView}.
     42  * {@code android:entries} can also be used to specify an
     43  * {@link com.android.setupwizardlib.items.ItemHierarchy} to be used with this layout in XML.
     44  *
     45  * @see SetupWizardItemsLayout
     46  */
     47 public class SetupWizardRecyclerLayout extends SetupWizardLayout {
     48 
     49     private static final String TAG = "RecyclerLayout";
     50 
     51     private RecyclerView.Adapter mAdapter;
     52     private RecyclerView mRecyclerView;
     53     private View mHeader;
     54 
     55     private DividerItemDecoration mDividerDecoration;
     56     private Drawable mDefaultDivider;
     57     private Drawable mDivider;
     58     private int mDividerInset;
     59 
     60     public SetupWizardRecyclerLayout(Context context) {
     61         this(context, 0, 0);
     62     }
     63 
     64     public SetupWizardRecyclerLayout(Context context, int template, int containerId) {
     65         super(context, template, containerId);
     66         init(context, null, 0);
     67     }
     68 
     69     public SetupWizardRecyclerLayout(Context context, AttributeSet attrs) {
     70         super(context, attrs);
     71         init(context, attrs, 0);
     72     }
     73 
     74     public SetupWizardRecyclerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
     75         super(context, attrs, defStyleAttr);
     76         init(context, attrs, defStyleAttr);
     77     }
     78 
     79     private void init(Context context, AttributeSet attrs, int defStyleAttr) {
     80         final TypedArray a = context.obtainStyledAttributes(attrs,
     81                 R.styleable.SuwSetupWizardRecyclerItemsLayout, defStyleAttr, 0);
     82         final int xml = a.getResourceId(
     83                 R.styleable.SuwSetupWizardRecyclerItemsLayout_android_entries, 0);
     84         if (xml != 0) {
     85             final ItemGroup inflated = (ItemGroup) new ItemInflater(context).inflate(xml);
     86             mAdapter = new RecyclerItemAdapter(inflated);
     87             mAdapter.setHasStableIds(a.getBoolean(
     88                     R.styleable.SuwSetupWizardRecyclerItemsLayout_suwHasStableIds, false));
     89             setAdapter(mAdapter);
     90         }
     91         int dividerInset = a.getDimensionPixelSize(
     92                 R.styleable.SuwSetupWizardRecyclerItemsLayout_suwDividerInset, 0);
     93         if (dividerInset == 0) {
     94             dividerInset = getResources()
     95                     .getDimensionPixelSize(R.dimen.suw_items_icon_divider_inset);
     96         }
     97         setDividerInset(dividerInset);
     98         a.recycle();
     99     }
    100 
    101     @Override
    102     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    103         super.onLayout(changed, left, top, right, bottom);
    104         if (mDivider == null) {
    105             // Update divider in case layout direction has just been resolved
    106             updateDivider();
    107         }
    108     }
    109 
    110     public RecyclerView.Adapter getAdapter() {
    111         return mAdapter;
    112     }
    113 
    114     public void setAdapter(RecyclerView.Adapter adapter) {
    115         mAdapter = adapter;
    116         getRecyclerView().setAdapter(adapter);
    117     }
    118 
    119     public RecyclerView getRecyclerView() {
    120         return mRecyclerView;
    121     }
    122 
    123     @Override
    124     protected ViewGroup findContainer(int containerId) {
    125         if (containerId == 0) {
    126             containerId = R.id.suw_recycler_view;
    127         }
    128         return super.findContainer(containerId);
    129     }
    130 
    131     @Override
    132     protected void onTemplateInflated() {
    133         initRecyclerView((RecyclerView) findViewById(R.id.suw_recycler_view));
    134     }
    135 
    136     protected void initRecyclerView(RecyclerView recyclerView) {
    137         mRecyclerView = recyclerView;
    138         mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
    139         if (mRecyclerView instanceof HeaderRecyclerView) {
    140             mHeader = ((HeaderRecyclerView) mRecyclerView).getHeader();
    141         }
    142         mDividerDecoration = DividerItemDecoration.getDefault(getContext());
    143         mRecyclerView.addItemDecoration(mDividerDecoration);
    144     }
    145 
    146     @Override
    147     protected View onInflateTemplate(LayoutInflater inflater, int template) {
    148         if (template == 0) {
    149             template = R.layout.suw_recycler_template;
    150         }
    151         return super.onInflateTemplate(inflater, template);
    152     }
    153 
    154     @Override
    155     protected View findManagedViewById(int id) {
    156         if (mHeader != null) {
    157             final View view = mHeader.findViewById(id);
    158             if (view != null) {
    159                 return view;
    160             }
    161         }
    162         return super.findViewById(id);
    163     }
    164 
    165     @Override
    166     public void requireScrollToBottom() {
    167         final NavigationBar navigationBar = getNavigationBar();
    168         final RecyclerView recyclerView = getRecyclerView();
    169         if (navigationBar != null && recyclerView != null) {
    170             RecyclerViewRequireScrollHelper.requireScroll(navigationBar, recyclerView);
    171         } else {
    172             Log.e(TAG, "Both suw_layout_navigation_bar and suw_recycler_view must exist in"
    173                     + " the template to require scrolling.");
    174         }
    175     }
    176 
    177     /**
    178      * Sets the start inset of the divider. This will use the default divider drawable set in the
    179      * theme and inset it {@code inset} pixels to the right (or left in RTL layouts).
    180      *
    181      * @param inset The number of pixels to inset on the "start" side of the list divider. Typically
    182      *              this will be either {@code @dimen/suw_items_icon_divider_inset} or
    183      *              {@code @dimen/suw_items_text_divider_inset}.
    184      */
    185     public void setDividerInset(int inset) {
    186         mDividerInset = inset;
    187         updateDivider();
    188     }
    189 
    190     public int getDividerInset() {
    191         return mDividerInset;
    192     }
    193 
    194     private void updateDivider() {
    195         boolean shouldUpdate = true;
    196         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    197             shouldUpdate = isLayoutDirectionResolved();
    198         }
    199         if (shouldUpdate) {
    200             if (mDefaultDivider == null) {
    201                 mDefaultDivider = mDividerDecoration.getDivider();
    202             }
    203             mDivider = DrawableLayoutDirectionHelper.createRelativeInsetDrawable(mDefaultDivider,
    204                     mDividerInset /* start */, 0 /* top */, 0 /* end */, 0 /* bottom */, this);
    205             mDividerDecoration.setDivider(mDivider);
    206         }
    207     }
    208 
    209     public Drawable getDivider() {
    210         return mDivider;
    211     }
    212 }
    213