[SuwLib] Support preference v14
Add SetupWizardPreferenceLayout to support Preference v14 framework. Bug: 26994868 Change-Id: I3b7a4b57cb4df6c46fdd868357bcbdaad39f1feb
This commit is contained in:
parent
15391fc05a
commit
3885d8491a
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<com.android.setupwizardlib.view.StickyHeaderRecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/suw_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:scrollbars="vertical"
|
||||
app:suwHeader="@layout/suw_list_header" />
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/suw_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scrollbars="vertical" />
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/suw_layout_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<com.android.setupwizardlib.view.NavigationBar
|
||||
android:id="@+id/suw_layout_navigation_bar"
|
||||
style="@style/SuwNavBarTheme"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/suw_navbar_height" />
|
||||
|
||||
</LinearLayout>
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
<resources>
|
||||
|
||||
<item name="suw_preference_recycler_view" type="layout">@layout/suw_preference_recycler_view_normal</item>
|
||||
<item name="suw_preference_template" type="layout">@layout/suw_no_scroll_template_header_collapsed</item>
|
||||
<item name="suw_recycler_template" type="layout">@layout/suw_recycler_template_header_collapsed</item>
|
||||
<item name="suw_recycler_template_short" type="layout">@layout/suw_recycler_template_header_collapsed</item>
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
<resources>
|
||||
|
||||
<item name="suw_preference_recycler_view" type="layout">@layout/suw_preference_recycler_view_normal</item>
|
||||
<item name="suw_preference_template" type="layout">@layout/suw_no_scroll_template_card_wide</item>
|
||||
<item name="suw_recycler_template" type="layout">@layout/suw_recycler_template_card_wide</item>
|
||||
<item name="suw_recycler_template_short" type="layout">@layout/suw_recycler_template_card_wide</item>
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
<resources>
|
||||
|
||||
<item name="suw_preference_recycler_view" type="layout">@layout/suw_preference_recycler_view_normal</item>
|
||||
<item name="suw_preference_template" type="layout">@layout/suw_no_scroll_template_card</item>
|
||||
<item name="suw_recycler_template" type="layout">@layout/suw_recycler_template_card</item>
|
||||
<item name="suw_recycler_template_short" type="layout">@layout/suw_recycler_template_card</item>
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
<resources>
|
||||
|
||||
<item name="suw_preference_recycler_view" type="layout">@layout/suw_preference_recycler_view_header</item>
|
||||
<item name="suw_preference_template" type="layout">@layout/suw_preference_template_header</item>
|
||||
<item name="suw_recycler_template" type="layout">@layout/suw_recycler_template_header</item>
|
||||
<item name="suw_recycler_template_short" type="layout">@layout/suw_recycler_template_header_collapsed</item>
|
||||
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.setupwizardlib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
/**
|
||||
* A layout to be used with {@code PreferenceFragment} in v14 support library. This can be specified
|
||||
* as the {@code android:layout} in the {@code app:preferenceFragmentStyle} in
|
||||
* {@code app:preferenceTheme}.
|
||||
*
|
||||
* <p />Example:
|
||||
* <pre>{@code
|
||||
* <style android:name="MyActivityTheme">
|
||||
* <item android:name="preferenceTheme">@style/MyPreferenceTheme</item>
|
||||
* </style>
|
||||
*
|
||||
* <style android:name="MyPreferenceTheme">
|
||||
* <item android:name="preferenceFragmentStyle">@style/MyPreferenceFragmentStyle</item>
|
||||
* </style>
|
||||
*
|
||||
* <style android:name="MyPreferenceFragmentStyle">
|
||||
* <item android:name="android:layout">@layout/my_preference_layout</item>
|
||||
* </style>
|
||||
* }</pre>
|
||||
*
|
||||
* where {@code my_preference_layout} is a layout that contains
|
||||
* {@link com.android.setupwizardlib.SetupWizardPreferenceLayout}.
|
||||
*
|
||||
* <p />Example:
|
||||
* <pre>{@code
|
||||
* <com.android.setupwizardlib.SetupWizardPreferenceLayout
|
||||
* xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* android:id="@id/list_container"
|
||||
* android:layout_width="match_parent"
|
||||
* android:layout_height="match_parent" />
|
||||
* }</pre>
|
||||
*
|
||||
* <p />Fragments using this layout <em>must</em> delegate {@code onCreateRecyclerView} to the
|
||||
* implementation in this class:
|
||||
* {@link #onCreateRecyclerView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)}
|
||||
*/
|
||||
public class SetupWizardPreferenceLayout extends SetupWizardRecyclerLayout {
|
||||
|
||||
private RecyclerView mRecyclerView;
|
||||
|
||||
public SetupWizardPreferenceLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public SetupWizardPreferenceLayout(Context context, int template, int containerId) {
|
||||
super(context, template, containerId);
|
||||
}
|
||||
|
||||
public SetupWizardPreferenceLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public SetupWizardPreferenceLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public RecyclerView getRecyclerView() {
|
||||
return mRecyclerView;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewGroup findContainer(int containerId) {
|
||||
if (containerId == 0) {
|
||||
containerId = R.id.suw_layout_content;
|
||||
}
|
||||
return super.findContainer(containerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method must be called in {@code PreferenceFragment#onCreateRecyclerView}.
|
||||
*/
|
||||
public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
|
||||
Bundle savedInstanceState) {
|
||||
return mRecyclerView;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View onInflateTemplate(LayoutInflater inflater, int template) {
|
||||
if (template == 0) {
|
||||
template = R.layout.suw_preference_template;
|
||||
}
|
||||
return super.onInflateTemplate(inflater, template);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTemplateInflated() {
|
||||
// Inflate the recycler view here, so attributes on the decoration views can be applied
|
||||
// immediately.
|
||||
final LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
mRecyclerView = (RecyclerView) inflater.inflate(R.layout.suw_preference_recycler_view,
|
||||
this, false);
|
||||
initRecyclerView(mRecyclerView);
|
||||
}
|
||||
}
|
|
@ -17,193 +17,25 @@
|
|||
package com.android.setupwizardlib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.setupwizardlib.items.ItemGroup;
|
||||
import com.android.setupwizardlib.items.ItemInflater;
|
||||
import com.android.setupwizardlib.items.RecyclerItemAdapter;
|
||||
import com.android.setupwizardlib.util.DrawableLayoutDirectionHelper;
|
||||
import com.android.setupwizardlib.util.RecyclerViewRequireScrollHelper;
|
||||
import com.android.setupwizardlib.view.HeaderRecyclerView;
|
||||
import com.android.setupwizardlib.view.NavigationBar;
|
||||
|
||||
/**
|
||||
* A SetupWizardLayout for use with {@link com.android.setupwizardlib.items.RecyclerItemAdapter},
|
||||
* which displays a list of items using a RecyclerView. The items XML file can be specified through
|
||||
* {@code android:entries} attribute in the layout.
|
||||
*
|
||||
* @see com.android.setupwizardlib.SetupWizardItemsLayout
|
||||
* @deprecated Use {@link com.android.setupwizardlib.SetupWizardRecyclerLayout}
|
||||
*/
|
||||
public class SetupWizardRecyclerItemsLayout extends SetupWizardLayout {
|
||||
|
||||
private static final String TAG = "RecyclerItemsLayout";
|
||||
|
||||
private RecyclerItemAdapter mAdapter;
|
||||
private RecyclerView mRecyclerView;
|
||||
|
||||
private TextView mHeaderTextView;
|
||||
private View mDecorationView;
|
||||
private DividerItemDecoration mDividerDecoration;
|
||||
private Drawable mDefaultDivider;
|
||||
private Drawable mDivider;
|
||||
private int mDividerInset;
|
||||
@Deprecated
|
||||
public class SetupWizardRecyclerItemsLayout extends SetupWizardRecyclerLayout {
|
||||
|
||||
public SetupWizardRecyclerItemsLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SetupWizardRecyclerItemsLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.SuwSetupWizardRecyclerItemsLayout, defStyleAttr, 0);
|
||||
final int xml = a.getResourceId(
|
||||
R.styleable.SuwSetupWizardRecyclerItemsLayout_android_entries, 0);
|
||||
if (xml != 0) {
|
||||
final ItemGroup inflated = (ItemGroup) new ItemInflater(context).inflate(xml);
|
||||
mAdapter = new RecyclerItemAdapter(inflated);
|
||||
mAdapter.setHasStableIds(a.getBoolean(
|
||||
R.styleable.SuwSetupWizardRecyclerItemsLayout_suwHasStableIds, false));
|
||||
setAdapter(mAdapter);
|
||||
}
|
||||
int dividerInset = a.getDimensionPixelSize(
|
||||
R.styleable.SuwSetupWizardRecyclerItemsLayout_suwDividerInset, 0);
|
||||
if (dividerInset == 0) {
|
||||
dividerInset = getResources()
|
||||
.getDimensionPixelSize(R.dimen.suw_items_icon_divider_inset);
|
||||
}
|
||||
setDividerInset(dividerInset);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
if (mDivider == null) {
|
||||
// Update divider in case layout direction has just been resolved
|
||||
updateDivider();
|
||||
}
|
||||
}
|
||||
|
||||
public RecyclerItemAdapter getAdapter() {
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
public void setAdapter(RecyclerItemAdapter adapter) {
|
||||
mAdapter = adapter;
|
||||
getRecyclerView().setAdapter(adapter);
|
||||
}
|
||||
|
||||
public RecyclerView getRecyclerView() {
|
||||
return mRecyclerView;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewGroup findContainer(int containerId) {
|
||||
if (containerId == 0) {
|
||||
containerId = R.id.suw_recycler_view;
|
||||
}
|
||||
return super.findContainer(containerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTemplateInflated() {
|
||||
mRecyclerView = (RecyclerView) findViewById(R.id.suw_recycler_view);
|
||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
if (mRecyclerView instanceof HeaderRecyclerView) {
|
||||
final View header = ((HeaderRecyclerView) mRecyclerView).getHeader();
|
||||
mHeaderTextView = (TextView) header.findViewById(R.id.suw_layout_title);
|
||||
mDecorationView = header.findViewById(R.id.suw_layout_decor);
|
||||
}
|
||||
mDividerDecoration = DividerItemDecoration.getDefault(getContext());
|
||||
mRecyclerView.addItemDecoration(mDividerDecoration);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View onInflateTemplate(LayoutInflater inflater, int template) {
|
||||
if (template == 0) {
|
||||
template = R.layout.suw_recycler_template;
|
||||
}
|
||||
return super.onInflateTemplate(inflater, template);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextView getHeaderTextView() {
|
||||
if (mHeaderTextView != null) {
|
||||
return mHeaderTextView;
|
||||
} else {
|
||||
return super.getHeaderTextView();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View getDecorationView() {
|
||||
if (mDecorationView != null) {
|
||||
return mDecorationView;
|
||||
} else {
|
||||
return super.getDecorationView();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requireScrollToBottom() {
|
||||
final NavigationBar navigationBar = getNavigationBar();
|
||||
final RecyclerView recyclerView = getRecyclerView();
|
||||
if (navigationBar != null && recyclerView != null) {
|
||||
RecyclerViewRequireScrollHelper.requireScroll(navigationBar, recyclerView);
|
||||
} else {
|
||||
Log.e(TAG, "Both suw_layout_navigation_bar and suw_recycler_view must exist in"
|
||||
+ " the template to require scrolling.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the start inset of the divider. This will use the default divider drawable set in the
|
||||
* theme and inset it {@code inset} pixels to the right (or left in RTL layouts).
|
||||
*
|
||||
* @param inset The number of pixels to inset on the "start" side of the list divider. Typically
|
||||
* this will be either {@code @dimen/suw_items_icon_divider_inset} or
|
||||
* {@code @dimen/suw_items_text_divider_inset}.
|
||||
*/
|
||||
public void setDividerInset(int inset) {
|
||||
mDividerInset = inset;
|
||||
updateDivider();
|
||||
}
|
||||
|
||||
public int getDividerInset() {
|
||||
return mDividerInset;
|
||||
}
|
||||
|
||||
private void updateDivider() {
|
||||
boolean shouldUpdate = true;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
shouldUpdate = isLayoutDirectionResolved();
|
||||
}
|
||||
if (shouldUpdate) {
|
||||
if (mDefaultDivider == null) {
|
||||
mDefaultDivider = mDividerDecoration.getDivider();
|
||||
}
|
||||
mDivider = DrawableLayoutDirectionHelper.createRelativeInsetDrawable(mDefaultDivider,
|
||||
mDividerInset /* start */, 0 /* top */, 0 /* end */, 0 /* bottom */, this);
|
||||
mDividerDecoration.setDivider(mDivider);
|
||||
}
|
||||
}
|
||||
|
||||
public Drawable getDivider() {
|
||||
return mDivider;
|
||||
return (RecyclerItemAdapter) super.getAdapter();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.setupwizardlib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.setupwizardlib.items.ItemGroup;
|
||||
import com.android.setupwizardlib.items.ItemInflater;
|
||||
import com.android.setupwizardlib.items.RecyclerItemAdapter;
|
||||
import com.android.setupwizardlib.util.DrawableLayoutDirectionHelper;
|
||||
import com.android.setupwizardlib.util.RecyclerViewRequireScrollHelper;
|
||||
import com.android.setupwizardlib.view.HeaderRecyclerView;
|
||||
import com.android.setupwizardlib.view.NavigationBar;
|
||||
|
||||
/**
|
||||
* A setup wizard layout for use with {@link android.support.v7.widget.RecyclerView}.
|
||||
* {@code android:entries} can also be used to specify an
|
||||
* {@link com.android.setupwizardlib.items.ItemHierarchy} to be used with this layout in XML.
|
||||
*
|
||||
* @see SetupWizardItemsLayout
|
||||
*/
|
||||
public class SetupWizardRecyclerLayout extends SetupWizardLayout {
|
||||
|
||||
private static final String TAG = "RecyclerLayout";
|
||||
|
||||
private RecyclerView.Adapter mAdapter;
|
||||
private RecyclerView mRecyclerView;
|
||||
|
||||
private TextView mHeaderTextView;
|
||||
private View mDecorationView;
|
||||
private DividerItemDecoration mDividerDecoration;
|
||||
private Drawable mDefaultDivider;
|
||||
private Drawable mDivider;
|
||||
private int mDividerInset;
|
||||
|
||||
public SetupWizardRecyclerLayout(Context context) {
|
||||
this(context, 0, 0);
|
||||
}
|
||||
|
||||
public SetupWizardRecyclerLayout(Context context, int template, int containerId) {
|
||||
super(context, template, containerId);
|
||||
init(context, null, 0);
|
||||
}
|
||||
|
||||
public SetupWizardRecyclerLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SetupWizardRecyclerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.SuwSetupWizardRecyclerItemsLayout, defStyleAttr, 0);
|
||||
final int xml = a.getResourceId(
|
||||
R.styleable.SuwSetupWizardRecyclerItemsLayout_android_entries, 0);
|
||||
if (xml != 0) {
|
||||
final ItemGroup inflated = (ItemGroup) new ItemInflater(context).inflate(xml);
|
||||
mAdapter = new RecyclerItemAdapter(inflated);
|
||||
mAdapter.setHasStableIds(a.getBoolean(
|
||||
R.styleable.SuwSetupWizardRecyclerItemsLayout_suwHasStableIds, false));
|
||||
setAdapter(mAdapter);
|
||||
}
|
||||
int dividerInset = a.getDimensionPixelSize(
|
||||
R.styleable.SuwSetupWizardRecyclerItemsLayout_suwDividerInset, 0);
|
||||
if (dividerInset == 0) {
|
||||
dividerInset = getResources()
|
||||
.getDimensionPixelSize(R.dimen.suw_items_icon_divider_inset);
|
||||
}
|
||||
setDividerInset(dividerInset);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
if (mDivider == null) {
|
||||
// Update divider in case layout direction has just been resolved
|
||||
updateDivider();
|
||||
}
|
||||
}
|
||||
|
||||
public RecyclerView.Adapter getAdapter() {
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
public void setAdapter(RecyclerView.Adapter adapter) {
|
||||
mAdapter = adapter;
|
||||
getRecyclerView().setAdapter(adapter);
|
||||
}
|
||||
|
||||
public RecyclerView getRecyclerView() {
|
||||
return mRecyclerView;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewGroup findContainer(int containerId) {
|
||||
if (containerId == 0) {
|
||||
containerId = R.id.suw_recycler_view;
|
||||
}
|
||||
return super.findContainer(containerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTemplateInflated() {
|
||||
initRecyclerView((RecyclerView) findViewById(R.id.suw_recycler_view));
|
||||
}
|
||||
|
||||
protected void initRecyclerView(RecyclerView recyclerView) {
|
||||
mRecyclerView = recyclerView;
|
||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
if (mRecyclerView instanceof HeaderRecyclerView) {
|
||||
final View header = ((HeaderRecyclerView) mRecyclerView).getHeader();
|
||||
mHeaderTextView = (TextView) header.findViewById(R.id.suw_layout_title);
|
||||
mDecorationView = header.findViewById(R.id.suw_layout_decor);
|
||||
}
|
||||
mDividerDecoration = DividerItemDecoration.getDefault(getContext());
|
||||
mRecyclerView.addItemDecoration(mDividerDecoration);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View onInflateTemplate(LayoutInflater inflater, int template) {
|
||||
if (template == 0) {
|
||||
template = R.layout.suw_recycler_template;
|
||||
}
|
||||
return super.onInflateTemplate(inflater, template);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextView getHeaderTextView() {
|
||||
if (mHeaderTextView != null) {
|
||||
return mHeaderTextView;
|
||||
} else {
|
||||
return super.getHeaderTextView();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View getDecorationView() {
|
||||
if (mDecorationView != null) {
|
||||
return mDecorationView;
|
||||
} else {
|
||||
return super.getDecorationView();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requireScrollToBottom() {
|
||||
final NavigationBar navigationBar = getNavigationBar();
|
||||
final RecyclerView recyclerView = getRecyclerView();
|
||||
if (navigationBar != null && recyclerView != null) {
|
||||
RecyclerViewRequireScrollHelper.requireScroll(navigationBar, recyclerView);
|
||||
} else {
|
||||
Log.e(TAG, "Both suw_layout_navigation_bar and suw_recycler_view must exist in"
|
||||
+ " the template to require scrolling.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the start inset of the divider. This will use the default divider drawable set in the
|
||||
* theme and inset it {@code inset} pixels to the right (or left in RTL layouts).
|
||||
*
|
||||
* @param inset The number of pixels to inset on the "start" side of the list divider. Typically
|
||||
* this will be either {@code @dimen/suw_items_icon_divider_inset} or
|
||||
* {@code @dimen/suw_items_text_divider_inset}.
|
||||
*/
|
||||
public void setDividerInset(int inset) {
|
||||
mDividerInset = inset;
|
||||
updateDivider();
|
||||
}
|
||||
|
||||
public int getDividerInset() {
|
||||
return mDividerInset;
|
||||
}
|
||||
|
||||
private void updateDivider() {
|
||||
boolean shouldUpdate = true;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
shouldUpdate = isLayoutDirectionResolved();
|
||||
}
|
||||
if (shouldUpdate) {
|
||||
if (mDefaultDivider == null) {
|
||||
mDefaultDivider = mDividerDecoration.getDivider();
|
||||
}
|
||||
mDivider = DrawableLayoutDirectionHelper.createRelativeInsetDrawable(mDefaultDivider,
|
||||
mDividerInset /* start */, 0 /* top */, 0 /* end */, 0 /* bottom */, this);
|
||||
mDividerDecoration.setDivider(mDivider);
|
||||
}
|
||||
}
|
||||
|
||||
public Drawable getDivider() {
|
||||
return mDivider;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<!--
|
||||
Copyright (C) 2015 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<com.android.setupwizardlib.SetupWizardRecyclerLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.setupwizardlib.test;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.InsetDrawable;
|
||||
import android.os.Build;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.test.InstrumentationTestCase;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.setupwizardlib.SetupWizardPreferenceLayout;
|
||||
|
||||
public class SetupWizardPreferenceLayoutTest extends InstrumentationTestCase {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mContext = new ContextThemeWrapper(getInstrumentation().getContext(),
|
||||
R.style.SuwThemeMaterial_Light);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testDefaultTemplate() {
|
||||
SetupWizardPreferenceLayout layout = new TestLayout(mContext);
|
||||
assertPreferenceTemplateInflated(layout);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testGetRecyclerView() {
|
||||
SetupWizardPreferenceLayout layout = new TestLayout(mContext);
|
||||
assertPreferenceTemplateInflated(layout);
|
||||
assertNotNull("getRecyclerView should not be null", layout.getRecyclerView());
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testOnCreateRecyclerView() {
|
||||
SetupWizardPreferenceLayout layout = new TestLayout(mContext);
|
||||
assertPreferenceTemplateInflated(layout);
|
||||
final RecyclerView recyclerView = layout.onCreateRecyclerView(LayoutInflater.from(mContext),
|
||||
layout, null /* savedInstanceState */);
|
||||
assertNotNull("RecyclerView created should not be null", recyclerView);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testDividerInset() {
|
||||
SetupWizardPreferenceLayout layout = new TestLayout(mContext);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
|
||||
}
|
||||
assertPreferenceTemplateInflated(layout);
|
||||
|
||||
layout.addView(layout.onCreateRecyclerView(LayoutInflater.from(mContext), layout,
|
||||
null /* savedInstanceState */));
|
||||
|
||||
layout.setDividerInset(10);
|
||||
assertEquals("Divider inset should be 10", 10, layout.getDividerInset());
|
||||
|
||||
final Drawable divider = layout.getDivider();
|
||||
assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
|
||||
}
|
||||
|
||||
private void assertPreferenceTemplateInflated(SetupWizardPreferenceLayout layout) {
|
||||
View contentContainer = layout.findViewById(R.id.suw_layout_content);
|
||||
assertTrue("@id/suw_layout_content should be a ViewGroup",
|
||||
contentContainer instanceof ViewGroup);
|
||||
|
||||
if (layout instanceof TestLayout) {
|
||||
assertNotNull("Header text view should not be null",
|
||||
((TestLayout) layout).getHeaderTextView());
|
||||
assertNotNull("Decoration view should not be null",
|
||||
((TestLayout) layout).getDecorationView());
|
||||
}
|
||||
}
|
||||
|
||||
// Make some methods public for testing
|
||||
public static class TestLayout extends SetupWizardPreferenceLayout {
|
||||
|
||||
public TestLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextView getHeaderTextView() {
|
||||
return super.getHeaderTextView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getDecorationView() {
|
||||
return super.getDecorationView();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.setupwizardlib.test;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.InsetDrawable;
|
||||
import android.os.Build;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.test.InstrumentationTestCase;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.setupwizardlib.SetupWizardRecyclerLayout;
|
||||
|
||||
public class SetupWizardRecyclerLayoutTest extends InstrumentationTestCase {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mContext = new ContextThemeWrapper(getInstrumentation().getContext(),
|
||||
R.style.SuwThemeMaterial_Light);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testDefaultTemplate() {
|
||||
SetupWizardRecyclerLayout layout = new TestLayout(mContext);
|
||||
assertRecyclerTemplateInflated(layout);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testInflateFromXml() {
|
||||
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
SetupWizardRecyclerLayout layout = (SetupWizardRecyclerLayout)
|
||||
inflater.inflate(R.layout.test_recycler_layout, null);
|
||||
assertRecyclerTemplateInflated(layout);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testGetRecyclerView() {
|
||||
SetupWizardRecyclerLayout layout = new TestLayout(mContext);
|
||||
assertRecyclerTemplateInflated(layout);
|
||||
assertNotNull("getRecyclerView should not be null", layout.getRecyclerView());
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testAdapter() {
|
||||
SetupWizardRecyclerLayout layout = new TestLayout(mContext);
|
||||
assertRecyclerTemplateInflated(layout);
|
||||
|
||||
final RecyclerView.Adapter adapter = new RecyclerView.Adapter() {
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
|
||||
return new RecyclerView.ViewHolder(new View(parent.getContext())) {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
layout.setAdapter(adapter);
|
||||
|
||||
final RecyclerView.Adapter gotAdapter = layout.getAdapter();
|
||||
// Note: The wrapped adapter should be returned, not the HeaderAdapter.
|
||||
assertSame("Adapter got from SetupWizardLayout should be same as set",
|
||||
adapter, gotAdapter);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testDividerInset() {
|
||||
SetupWizardRecyclerLayout layout = new TestLayout(mContext);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
|
||||
}
|
||||
assertRecyclerTemplateInflated(layout);
|
||||
|
||||
layout.setDividerInset(10);
|
||||
assertEquals("Divider inset should be 10", 10, layout.getDividerInset());
|
||||
|
||||
final Drawable divider = layout.getDivider();
|
||||
assertTrue("Divider should be instance of InsetDrawable", divider instanceof InsetDrawable);
|
||||
}
|
||||
|
||||
private void assertRecyclerTemplateInflated(SetupWizardRecyclerLayout layout) {
|
||||
View recyclerView = layout.findViewById(R.id.suw_recycler_view);
|
||||
assertTrue("@id/suw_recycler_view should be a RecyclerView",
|
||||
recyclerView instanceof RecyclerView);
|
||||
|
||||
if (layout instanceof TestLayout) {
|
||||
assertNotNull("Header text view should not be null",
|
||||
((TestLayout) layout).getHeaderTextView());
|
||||
}
|
||||
}
|
||||
|
||||
// Make some methods public for testing
|
||||
public static class TestLayout extends SetupWizardRecyclerLayout {
|
||||
|
||||
public TestLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextView getHeaderTextView() {
|
||||
return super.getHeaderTextView();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -55,14 +55,7 @@
|
|||
<FrameLayout
|
||||
android:id="@+id/suw_layout_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- Temporary solution to work with PreferenceFragment v14 -->
|
||||
<FrameLayout android:id="@+id/list_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</FrameLayout>
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<include layout="@layout/suw_progress_bar_stub" />
|
||||
|
||||
|
|
|
@ -56,14 +56,7 @@
|
|||
<FrameLayout
|
||||
android:id="@+id/suw_layout_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- Temporary solution to work with PreferenceFragment v14 -->
|
||||
<FrameLayout android:id="@+id/list_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</FrameLayout>
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<include layout="@layout/suw_progress_bar_stub" />
|
||||
|
||||
|
|
|
@ -56,14 +56,7 @@
|
|||
android:id="@+id/suw_layout_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<!-- Temporary solution to work with PreferenceFragment v14 -->
|
||||
<FrameLayout android:id="@+id/list_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</FrameLayout>
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
|
|
@ -45,14 +45,7 @@
|
|||
<FrameLayout android:id="@+id/suw_layout_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<!-- Temporary solution to work with PreferenceFragment v14 -->
|
||||
<FrameLayout android:id="@+id/list_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</FrameLayout>
|
||||
android:layout_weight="1" />
|
||||
|
||||
<com.android.setupwizardlib.view.NavigationBar
|
||||
android:id="@+id/suw_layout_navigation_bar"
|
||||
|
|
|
@ -7,7 +7,7 @@ apply plugin: 'dist'
|
|||
apply from: 'build.gradle'
|
||||
apply from: '../tools/gradle/docs.gradle'
|
||||
|
||||
task docs(dependsOn: 'javadocPlatformRelease')
|
||||
task docs(dependsOn: 'javadocFullSupportRelease')
|
||||
|
||||
android.lintOptions {
|
||||
abortOnError true
|
||||
|
|
Loading…
Reference in a new issue