am 01851b3e: Merge "LinearLayoutManager examples" into klp-modular-dev

* commit '01851b3efd18fd60db8a13563e1374a84b3c89fe':
  LinearLayoutManager examples
This commit is contained in:
Yigit Boyar
2014-03-28 23:03:53 +00:00
committed by Android Git Automerger
7 changed files with 512 additions and 115 deletions

View File

@@ -38,6 +38,7 @@
android:compatibleWidthLimitDp="480" />
<application android:label="@string/activity_sample_code"
android:supportsRtl="true"
android:icon="@drawable/app_sample_code"
android:hardwareAccelerated="true">
@@ -182,5 +183,14 @@
</intent-filter>
</activity>
<activity android:name=".widget.LinearLayoutManagerActivity"
android:label="@string/linear_layout_manager"
android:theme="@style/Theme.AppCompat">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.example.android.supportv7.SAMPLE_CODE" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/spinner"/>
<android.support.v7.widget.RecyclerView
android:layout_width="fill_parent"
android:layout_height="100dp"
android:id="@+id/config_recycler_view"/>
<android.support.v7.widget.RecyclerView
android:scrollbarStyle="insideOverlay"
android:scrollbars="horizontal|vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/recycler_view"/>
</LinearLayout>

View File

@@ -96,4 +96,9 @@
<string name="sample_media_route_activity_presentation">Local Playback on Presentation Display</string>
<string name="recycler_view">RecyclerView</string>
<string name="linear_layout_manager">Linear Layout Manager</string>
<string name="checkbox_orientation">Horz.</string>
<string name="checkbox_reverse">Rev.</string>
<string name="checkbox_layout_dir">Layout Dir</string>
<string name="checkbox_stack_from_end">Stack From End</string>
</resources>

View File

@@ -0,0 +1,243 @@
/*
* Copyright (C) 2014 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.example.android.supportv7.widget;
import com.example.android.supportv7.Cheeses;
import com.example.android.supportv7.widget.adapter.SimpleStringAdapter;
import com.example.android.supportv7.widget.decorator.DividerItemDecoration;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.example.android.supportv7.R;
/**
* A sample activity that uses {@link android.support.v7.widget.LinearLayoutManager}.
*/
public class LinearLayoutManagerActivity extends Activity {
private LinearLayoutManager mListLayoutManager;
private RecyclerView mRecyclerView;
private DividerItemDecoration mDividerItemDecoration;
private ConfigToggle[] mConfigToggles;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_linear_layout_manager);
initConfig();
initRecyclerView();
initSpinner();
}
private void initRecyclerView() {
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mListLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mListLayoutManager);
mRecyclerView.setAdapter(new SimpleStringAdapter(this, Cheeses.sCheeseStrings));
mDividerItemDecoration = new DividerItemDecoration(this,
mListLayoutManager.getOrientation());
mRecyclerView.addItemDecoration(mDividerItemDecoration);
}
private void initConfig() {
RecyclerView configView = (RecyclerView) findViewById(R.id.config_recycler_view);
initToggles();
configView.setAdapter(mConfigAdapter);
configView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL,
false));
configView.setHasFixedSize(true);
}
private void initSpinner() {
Spinner spinner = (Spinner) findViewById(R.id.spinner);
spinner.setAdapter(new BaseAdapter() {
@Override
public int getCount() {
return mRecyclerView.getAdapter().getItemCount();
}
@Override
public Integer getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = new TextView(parent.getContext());
}
((TextView) convertView).setText("" + position);
return convertView;
}
});
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mRecyclerView.scrollToPosition(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
private void initToggles() {
mConfigToggles = new ConfigToggle[]{
new ConfigToggle(R.string.checkbox_orientation) {
@Override
public boolean isChecked() {
return mListLayoutManager.getOrientation() == LinearLayoutManager.HORIZONTAL;
}
@Override
public void onChange(boolean newValue) {
mListLayoutManager.setOrientation(newValue ? LinearLayoutManager.HORIZONTAL
: LinearLayoutManager.VERTICAL);
mDividerItemDecoration.setOrientation(mListLayoutManager.getOrientation());
}
},
new ConfigToggle(R.string.checkbox_reverse) {
@Override
public boolean isChecked() {
return mListLayoutManager.getReverseLayout();
}
@Override
public void onChange(boolean newValue) {
mListLayoutManager.setReverseLayout(newValue);
}
},
new ConfigToggle(R.string.checkbox_layout_dir) {
@Override
public boolean isChecked() {
return ViewCompat.getLayoutDirection(mRecyclerView) ==
ViewCompat.LAYOUT_DIRECTION_RTL;
}
@Override
public void onChange(boolean newValue) {
ViewCompat.setLayoutDirection(mRecyclerView, newValue ?
ViewCompat.LAYOUT_DIRECTION_RTL : ViewCompat.LAYOUT_DIRECTION_LTR);
}
},
new ConfigToggle(R.string.checkbox_stack_from_end) {
@Override
public boolean isChecked() {
return mListLayoutManager.getStackFromEnd();
}
@Override
public void onChange(boolean newValue) {
mListLayoutManager.setStackFromEnd(newValue);
}
}
};
}
private class ConfigViewHolder extends RecyclerView.ViewHolder
implements CompoundButton.OnCheckedChangeListener {
private CheckBox mCheckBox;
private ConfigToggle mConfigToggle;
public ConfigViewHolder(View itemView) {
super(itemView);
mCheckBox = (CheckBox) itemView;
mCheckBox.setOnCheckedChangeListener(this);
}
public void render(ConfigToggle toggle) {
mConfigToggle = toggle;
mCheckBox.setText(toggle.getText());
mCheckBox.setChecked(toggle.isChecked());
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mConfigToggle != null) {
mConfigToggle.onChange(isChecked);
}
}
}
private abstract class ConfigToggle {
private String mLabel;
protected ConfigToggle(int labelId) {
mLabel = getResources().getString(labelId);
}
public String getText() {
return mLabel;
}
abstract public boolean isChecked();
abstract public void onChange(boolean newValue);
}
private RecyclerView.Adapter mConfigAdapter = new RecyclerView.Adapter<ConfigViewHolder>() {
@Override
public ConfigViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ConfigViewHolder(new CheckBox(parent.getContext()));
}
@Override
public void onBindViewHolder(ConfigViewHolder holder, int position) {
ConfigToggle toggle = mConfigToggles[position];
holder.render(toggle);
}
@Override
public int getItemCount() {
return mConfigToggles.length;
}
};
}

View File

@@ -17,30 +17,23 @@
package com.example.android.supportv7.widget;
import android.R;
import com.example.android.supportv7.Cheeses;
import com.example.android.supportv7.widget.adapter.SimpleStringAdapter;
import com.example.android.supportv7.widget.decorator.DividerItemDecoration;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.example.android.supportv7.Cheeses;
import java.util.ArrayList;
import java.util.Collections;
public class RecyclerViewActivity extends Activity {
private static final String TAG = "RecyclerViewActivity";
private RecyclerView mRecyclerView;
@@ -54,12 +47,26 @@ public class RecyclerViewActivity extends Activity {
rv.setHasFixedSize(true);
rv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
rv.setAdapter(new MyAdapter(Cheeses.sCheeseStrings));
rv.addItemDecoration(new DividerItemDecoration(this));
rv.setAdapter(new SimpleStringAdapter(this, Cheeses.sCheeseStrings) {
@Override
public SimpleStringAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
final SimpleStringAdapter.ViewHolder vh = super
.onCreateViewHolder(parent, viewType);
vh.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final int pos = vh.getPosition();
if (pos + 1 < getItemCount()) {
swap(pos, pos + 1);
}
}
});
return vh;
}
});
rv.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
setContentView(rv);
mRecyclerView = rv;
}
@@ -82,8 +89,11 @@ public class RecyclerViewActivity extends Activity {
* A basic ListView-style LayoutManager.
*/
class MyLayoutManager extends RecyclerView.LayoutManager {
private static final String TAG = "MyLayoutManager";
private int mFirstPosition;
private final int mScrollDistance;
public MyLayoutManager(Context c) {
@@ -268,102 +278,4 @@ public class RecyclerViewActivity extends Activity {
}
}
}
class MyAdapter extends RecyclerView.Adapter<ViewHolder> {
private int mBackground;
private ArrayList<String> mValues;
public MyAdapter(String[] strings) {
TypedValue val = new TypedValue();
RecyclerViewActivity.this.getTheme().resolveAttribute(
R.attr.selectableItemBackground, val, true);
mBackground = val.resourceId;
mValues = new ArrayList<String>();
Collections.addAll(mValues, strings);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final ViewHolder h = new ViewHolder(new TextView(RecyclerViewActivity.this));
h.textView.setMinimumHeight(128);
h.textView.setFocusable(true);
h.textView.setBackgroundResource(mBackground);
h.textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final int pos = h.getPosition();
if (mValues.size() > pos + 1) {
final String t = mValues.get(pos);
mValues.set(pos, mValues.get(pos + 1));
mValues.set(pos + 1, t);
notifyItemRemoved(pos);
notifyItemInserted(pos + 1);
}
}
});
return h;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.textView.setText(mValues.get(position));
}
@Override
public int getItemCount() {
return mValues.size();
}
}
static class ViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public ViewHolder(TextView v) {
super(v);
textView = v;
}
@Override
public String toString() {
return super.toString() + " '" + textView.getText();
}
}
static class DividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[] {
R.attr.listDivider
};
private Drawable mDivider;
public DividerItemDecoration(Context context) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}
public DividerItemDecoration(Drawable divider) {
mDivider = divider;
}
@Override
public void onDraw(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final int top = child.getBottom();
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
}
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2014 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.example.android.supportv7.widget.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
public class SimpleStringAdapter extends RecyclerView.Adapter<SimpleStringAdapter.ViewHolder> {
private int mBackground;
private ArrayList<String> mValues;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public ViewHolder(TextView v) {
super(v);
textView = v;
}
@Override
public String toString() {
return super.toString() + " '" + textView.getText();
}
}
public SimpleStringAdapter(Context context, String[] strings) {
TypedValue val = new TypedValue();
if (context.getTheme() != null) {
context.getTheme().resolveAttribute(
android.R.attr.selectableItemBackground, val, true);
}
mBackground = val.resourceId;
mValues = new ArrayList<String>();
Collections.addAll(mValues, strings);
}
public void swap(int pos1, int pos2) {
String tmp = mValues.get(pos1);
mValues.set(pos1, mValues.get(pos2));
mValues.set(pos2, tmp);
notifyItemRemoved(pos1);
notifyItemInserted(pos2);
}
@Override
public SimpleStringAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final ViewHolder h = new ViewHolder(new TextView(parent.getContext()));
h.textView.setMinimumHeight(128);
h.textView.setPadding(20, 0, 20, 0);
h.textView.setFocusable(true);
h.textView.setBackgroundResource(mBackground);
return h;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.textView.setText(position + ":" + mValues.get(position));
}
@Override
public int getItemCount() {
return mValues.size();
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2014 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.example.android.supportv7.widget.decorator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
public DividerItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
@Override
public void onDraw(Canvas c, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
public void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}