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