├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── me │ │ └── xiazdong │ │ └── recyclerviewdemo │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── me │ │ │ └── xiazdong │ │ │ └── recyclerviewdemo │ │ │ ├── MainActivity.java │ │ │ ├── demo1 │ │ │ ├── Activity1.java │ │ │ ├── CustomAdapter.java │ │ │ ├── DefaultItemAnimator.java │ │ │ ├── DividerItemDecoration.java │ │ │ ├── NormalAdapter.java │ │ │ ├── NormalAdapterWrapper.java │ │ │ └── ObjectModel.java │ │ │ ├── demo2 │ │ │ ├── Activity2.java │ │ │ ├── DownloadAdapter.java │ │ │ ├── DownloadTask.java │ │ │ └── Job.java │ │ │ ├── demo3 │ │ │ ├── Activity3.java │ │ │ ├── NormalAdapter.java │ │ │ └── SimpleItemTouchCallback.java │ │ │ ├── demo4 │ │ │ ├── Activity4.java │ │ │ ├── Image.java │ │ │ └── ImageAdapter.java │ │ │ ├── demo5 │ │ │ ├── Activity5.java │ │ │ ├── EmptyRecyclerView.java │ │ │ └── NormalAdapter.java │ │ │ └── demo6 │ │ │ ├── Activity6.java │ │ │ └── QuickAdapter.java │ └── res │ │ ├── assets │ │ └── demo6.gif │ │ ├── drawable │ │ ├── bg.jpg │ │ ├── divider.jpg │ │ ├── item1_divider.xml │ │ ├── s1.jpg │ │ ├── s10.jpg │ │ ├── s2.jpg │ │ ├── s3.jpg │ │ ├── s4.jpg │ │ ├── s5.jpg │ │ ├── s6.jpg │ │ ├── s7.jpg │ │ ├── s8.jpg │ │ └── s9.jpg │ │ ├── layout │ │ ├── activity_1.xml │ │ ├── activity_2.xml │ │ ├── activity_3.xml │ │ ├── activity_4.xml │ │ ├── activity_5.xml │ │ ├── activity_6.xml │ │ ├── activity_7.xml │ │ ├── activity_main.xml │ │ ├── item_1.xml │ │ ├── item_3.xml │ │ ├── item_4.xml │ │ ├── item_5.xml │ │ ├── item_6.xml │ │ ├── item_download.xml │ │ ├── item_footer.xml │ │ └── item_header.xml │ │ ├── menu │ │ ├── menu_1.xml │ │ └── menu_5.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── me │ └── xiazdong │ └── recyclerviewdemo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | RecyclerViewDemo -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 24 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 49 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "24.0.2" 6 | 7 | defaultConfig { 8 | applicationId "me.xiazdong.recyclerviewdemo" 9 | minSdkVersion 14 10 | targetSdkVersion 24 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:24.0.0' 26 | compile 'com.android.support:recyclerview-v7:24.2.1' 27 | compile 'com.daimajia.numberprogressbar:library:1.2@aar' 28 | compile 'jp.wasabeef:recyclerview-animators:2.2.4' 29 | compile 'com.squareup.picasso:picasso:2.5.2' 30 | compile 'com.android.support:design:24.2.1' 31 | } 32 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/xiazdong/tech/android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/me/xiazdong/recyclerviewdemo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo; 2 | 3 | import android.content.Intent; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import me.xiazdong.recyclerviewdemo.demo1.Activity1; 9 | import me.xiazdong.recyclerviewdemo.demo2.Activity2; 10 | import me.xiazdong.recyclerviewdemo.demo3.Activity3; 11 | import me.xiazdong.recyclerviewdemo.demo4.Activity4; 12 | import me.xiazdong.recyclerviewdemo.demo5.Activity5; 13 | import me.xiazdong.recyclerviewdemo.demo6.Activity6; 14 | 15 | public class MainActivity extends AppCompatActivity{ 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_main); 21 | } 22 | 23 | public void jump(View view){ 24 | Intent intent = new Intent(); 25 | switch (view.getId()){ 26 | case R.id.btn_1: 27 | intent.setClass(this,Activity1.class); 28 | break; 29 | case R.id.btn_2: 30 | intent.setClass(this,Activity2.class); 31 | break; 32 | case R.id.btn_3: 33 | intent.setClass(this, Activity3.class); 34 | break; 35 | case R.id.btn_4: 36 | intent.setClass(this, Activity4.class); 37 | break; 38 | case R.id.btn_5: 39 | intent.setClass(this, Activity5.class); 40 | break; 41 | case R.id.btn_6: 42 | intent.setClass(this, Activity6.class); 43 | break; 44 | } 45 | startActivity(intent); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo1/Activity1.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo1; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.support.v7.widget.LinearLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.support.v7.widget.StaggeredGridLayoutManager; 8 | import android.view.Gravity; 9 | import android.view.LayoutInflater; 10 | import android.view.Menu; 11 | import android.view.MenuItem; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.BaseAdapter; 15 | import android.widget.TextView; 16 | import android.widget.Toast; 17 | 18 | import java.util.ArrayList; 19 | 20 | import me.xiazdong.recyclerviewdemo.R; 21 | 22 | 23 | /** 24 | * Demo1:RecyclerView的基本使用。 25 | * - 为RecyclerView添加OnItemClickListener接口。 26 | * - ItemDecoration的范例:DividerItemDecoration。 27 | * - 为RecyclerView实现Headerview和Footerview。 28 | */ 29 | public class Activity1 extends AppCompatActivity { 30 | 31 | private RecyclerView mRecyclerView; 32 | private ArrayList mData; 33 | private NormalAdapterWrapper mAdapter; 34 | private NormalAdapter mNoHeaderAdapter; 35 | private DividerItemDecoration mDecoration; 36 | private RecyclerView.LayoutManager mLayoutManager; 37 | 38 | @Override 39 | protected void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | setContentView(R.layout.activity_1); 42 | mRecyclerView = (RecyclerView) findViewById(R.id.rv); 43 | mDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST); 44 | mLayoutManager = new LinearLayoutManager(this); 45 | mRecyclerView.setLayoutManager(mLayoutManager); 46 | mRecyclerView.addItemDecoration(mDecoration); 47 | /* 48 | CustomAdapter adapter = new CustomAdapter(initData()); 49 | adapter.setOnClickListener(new CustomAdapter.OnClickListener() { 50 | @Override 51 | public void onItemClick(View view, int position) { 52 | Toast.makeText(Activity1.this,"position=" + position, Toast.LENGTH_SHORT).show(); 53 | } 54 | }); 55 | */ 56 | 57 | mNoHeaderAdapter = new NormalAdapter(mData = initData()); 58 | mAdapter = new NormalAdapterWrapper(mNoHeaderAdapter); 59 | View headerView = LayoutInflater.from(this).inflate(R.layout.item_header, mRecyclerView, false); 60 | View footerView = LayoutInflater.from(this).inflate(R.layout.item_footer, mRecyclerView, false); 61 | mAdapter.addFooterView(footerView); 62 | mAdapter.addHeaderView(headerView); 63 | mRecyclerView.setAdapter(mAdapter); 64 | } 65 | 66 | public ArrayList initData(){ 67 | ArrayList models = new ArrayList<>(); 68 | String[] titles = getResources().getStringArray(R.array.title_array); 69 | for(int i=0;i { 14 | 15 | public enum ITEM_TYPE{ 16 | ITEM_TYPE_HEADER, 17 | ITEM_TYPE_NORMAL, 18 | ITEM_TYPE_FOOTER 19 | } 20 | 21 | private ArrayList mDatas; 22 | private OnClickListener mListener; 23 | 24 | public CustomAdapter(ArrayList datas){ 25 | this.mDatas = datas; 26 | } 27 | 28 | @Override 29 | public int getItemViewType(int position) { 30 | if(position == 0){ 31 | return ITEM_TYPE.ITEM_TYPE_HEADER.ordinal(); 32 | } else if(position == mDatas.size() + 1){ 33 | return ITEM_TYPE.ITEM_TYPE_FOOTER.ordinal(); 34 | } else { 35 | return ITEM_TYPE.ITEM_TYPE_NORMAL.ordinal(); 36 | } 37 | } 38 | 39 | @Override 40 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 41 | View v = null; 42 | if(viewType == ITEM_TYPE.ITEM_TYPE_HEADER.ordinal()){ 43 | v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_header, parent, false); 44 | return new HeaderVH(v); 45 | } else if(viewType == ITEM_TYPE.ITEM_TYPE_FOOTER.ordinal()){ 46 | v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer, parent, false); 47 | return new FooterVH(v); 48 | } else if(viewType == ITEM_TYPE.ITEM_TYPE_NORMAL.ordinal()){ 49 | v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_1, parent, false); 50 | Log.i("onCreateViewHolder","onCreateViewHolder"); 51 | return new VH(v); 52 | } 53 | return null; 54 | //LayoutInflater.from(parent.getContext()).inflate(R.layout.item_1, null); 是不行的 55 | } 56 | 57 | @Override 58 | public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { 59 | if(holder instanceof HeaderVH){ 60 | ((HeaderVH)holder).text.setText("Header View"); 61 | ((HeaderVH)holder).image.setImageResource(R.mipmap.ic_launcher); 62 | } else if(holder instanceof FooterVH){ 63 | ((FooterVH)holder).image.setImageResource(R.mipmap.ic_launcher); 64 | } else if(holder instanceof VH){ 65 | ObjectModel model = mDatas.get(position - 1); 66 | ((VH)holder).number.setText(model.number + ""); 67 | ((VH)holder).title.setText(model.title); 68 | holder.itemView.setOnClickListener(new View.OnClickListener() { 69 | @Override 70 | public void onClick(View view) { 71 | if(mListener != null){ 72 | mListener.onItemClick(view, position - 1); 73 | } 74 | } 75 | }); 76 | } 77 | } 78 | 79 | @Override 80 | public int getItemCount() { 81 | return mDatas == null ? 2 : mDatas.size() + 2; 82 | } 83 | 84 | public void setOnClickListener(OnClickListener listener){ 85 | this.mListener = listener; 86 | } 87 | 88 | public interface OnClickListener{ 89 | void onItemClick(View view, int position); 90 | } 91 | 92 | public static class VH extends RecyclerView.ViewHolder{ 93 | public final TextView title; 94 | public final TextView number; 95 | public VH(View v) { 96 | super(v); 97 | title = (TextView) v.findViewById(R.id.title); 98 | number = (TextView) v.findViewById(R.id.number); 99 | } 100 | } 101 | 102 | public static class HeaderVH extends RecyclerView.ViewHolder{ 103 | public final TextView text; 104 | public final ImageView image; 105 | 106 | public HeaderVH(View v){ 107 | super(v); 108 | text = (TextView) v.findViewById(R.id.tv); 109 | image = (ImageView) v.findViewById(R.id.image); 110 | } 111 | } 112 | 113 | 114 | public static class FooterVH extends RecyclerView.ViewHolder{ 115 | public final ImageView image; 116 | 117 | public FooterVH(View v){ 118 | super(v); 119 | image = (ImageView) v.findViewById(R.id.image); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo1/DefaultItemAnimator.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo1; 2 | 3 | import android.support.v4.view.ViewCompat; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | import jp.wasabeef.recyclerview.animators.BaseItemAnimator; 7 | 8 | /** 9 | * Created by damonxia on 16/10/18. 10 | */ 11 | public class DefaultItemAnimator extends BaseItemAnimator{ 12 | 13 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 14 | ViewCompat.animate(holder.itemView) 15 | .alpha(0) 16 | .setDuration(getRemoveDuration()) 17 | .setListener(new DefaultRemoveVpaListener(holder)) 18 | .setStartDelay(getRemoveDelay(holder)) 19 | .start(); 20 | } 21 | 22 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 23 | ViewCompat.setAlpha(holder.itemView, 0); 24 | } 25 | 26 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 27 | ViewCompat.animate(holder.itemView) 28 | .alpha(1) 29 | .setDuration(getAddDuration()) 30 | .setListener(new DefaultAddVpaListener(holder)) 31 | .setStartDelay(getAddDelay(holder)) 32 | .start(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo1/DividerItemDecoration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 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 | package me.xiazdong.recyclerviewdemo.demo1; 17 | import android.content.Context; 18 | import android.content.res.TypedArray; 19 | import android.graphics.Canvas; 20 | import android.graphics.Rect; 21 | import android.graphics.drawable.Drawable; 22 | import android.support.v4.view.ViewCompat; 23 | import android.support.v7.widget.LinearLayoutManager; 24 | import android.support.v7.widget.RecyclerView; 25 | import android.view.View; 26 | 27 | import me.xiazdong.recyclerviewdemo.R; 28 | 29 | public class DividerItemDecoration extends RecyclerView.ItemDecoration { 30 | private static final int[] ATTRS = new int[]{ 31 | android.R.attr.listDivider 32 | }; 33 | public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; 34 | public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; 35 | private Drawable mDivider; 36 | private int mOrientation; 37 | public DividerItemDecoration(Context context, int orientation) { 38 | final TypedArray a = context.obtainStyledAttributes(ATTRS); 39 | mDivider = a.getDrawable(0); 40 | //mDivider = context.getResources().getDrawable(R.drawable.divider); 41 | a.recycle(); 42 | setOrientation(orientation); 43 | } 44 | 45 | public void setDividerDrawable(Drawable drawable){ 46 | this.mDivider = drawable; 47 | } 48 | public void setOrientation(int orientation) { 49 | if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { 50 | throw new IllegalArgumentException("invalid orientation"); 51 | } 52 | mOrientation = orientation; 53 | } 54 | 55 | /** 56 | * 画分割线 57 | * @param c 画布 58 | * @param parent 59 | */ 60 | @Override 61 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { 62 | if (mOrientation == VERTICAL_LIST) { 63 | drawVertical(c, parent); 64 | } else { 65 | drawHorizontal(c, parent); 66 | } 67 | } 68 | public void drawVertical(Canvas c, RecyclerView parent) { 69 | final int left = parent.getPaddingLeft(); 70 | final int right = parent.getWidth() - parent.getPaddingRight(); 71 | final int childCount = parent.getChildCount(); 72 | /** 73 | * 画每个item的分割线 74 | */ 75 | for (int i = 0; i < childCount; i++) { 76 | final View child = parent.getChildAt(i); 77 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 78 | .getLayoutParams(); 79 | final int top = child.getBottom() + params.bottomMargin + 80 | Math.round(ViewCompat.getTranslationY(child)); 81 | //mDivider.getIntrinsicHeight() 单位dp 82 | final int bottom = top + mDivider.getIntrinsicHeight(); 83 | mDivider.setBounds(left, top, right, bottom);/*规定好左上角和右下角*/ 84 | mDivider.draw(c); 85 | } 86 | } 87 | public void drawHorizontal(Canvas c, RecyclerView parent) { 88 | final int top = parent.getPaddingTop(); 89 | final int bottom = parent.getHeight() - parent.getPaddingBottom(); 90 | final int childCount = parent.getChildCount(); 91 | for (int i = 0; i < childCount; i++) { 92 | final View child = parent.getChildAt(i); 93 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 94 | .getLayoutParams(); 95 | final int left = child.getRight() + params.rightMargin + 96 | Math.round(ViewCompat.getTranslationX(child)); 97 | final int right = left + mDivider.getIntrinsicHeight(); 98 | mDivider.setBounds(left, top, right, bottom); 99 | mDivider.draw(c); 100 | } 101 | } 102 | 103 | /** 104 | * 确定divider的位置,设置在outRect中 105 | * 这个函数在计算RecyclerView中每个child大小时会用到 106 | */ 107 | @Override 108 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 109 | if (mOrientation == VERTICAL_LIST) { 110 | int position = ((RecyclerView.LayoutParams)view.getLayoutParams()).getViewLayoutPosition(); 111 | int count = parent.getAdapter().getItemCount(); 112 | if(position < count - 1) { 113 | outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); 114 | } 115 | } else { 116 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo1/NormalAdapter.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo1; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.TextView; 8 | 9 | import java.util.List; 10 | 11 | import me.xiazdong.recyclerviewdemo.R; 12 | 13 | public class NormalAdapter extends RecyclerView.Adapter{ 14 | 15 | private List mDatas; 16 | public NormalAdapter(List data) { 17 | this.mDatas = data; 18 | } 19 | 20 | @Override 21 | public void onBindViewHolder(VH holder, int position) { 22 | ObjectModel model = mDatas.get(position); 23 | holder.number.setText(model.number + ""); 24 | holder.title.setText(model.title); 25 | holder.itemView.setOnClickListener(new View.OnClickListener() { 26 | @Override 27 | public void onClick(View v) { 28 | //item 点击事件 29 | } 30 | }); 31 | } 32 | 33 | @Override 34 | public int getItemCount() { 35 | return mDatas.size(); 36 | } 37 | 38 | @Override 39 | public VH onCreateViewHolder(ViewGroup parent, int viewType) { 40 | View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_1, parent, false); 41 | return new VH(v); 42 | } 43 | 44 | public static class VH extends RecyclerView.ViewHolder{ 45 | public final TextView title; 46 | public final TextView number; 47 | public VH(View v) { 48 | super(v); 49 | title = (TextView) v.findViewById(R.id.title); 50 | number = (TextView) v.findViewById(R.id.number); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo1/NormalAdapterWrapper.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo1; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | 7 | public class NormalAdapterWrapper extends RecyclerView.Adapter{ 8 | 9 | enum ITEM_TYPE{ 10 | HEADER, 11 | FOOTER, 12 | NORMAL 13 | } 14 | 15 | private NormalAdapter mAdapter; 16 | private View mHeaderView; 17 | private View mFooterView; 18 | 19 | public NormalAdapterWrapper(NormalAdapter adapter){ 20 | mAdapter = adapter; 21 | } 22 | 23 | @Override 24 | public int getItemViewType(int position) { 25 | if(position == 0){ 26 | return ITEM_TYPE.HEADER.ordinal(); 27 | } else if(position == mAdapter.getItemCount() + 1){ 28 | return ITEM_TYPE.FOOTER.ordinal(); 29 | } else{ 30 | return ITEM_TYPE.NORMAL.ordinal(); 31 | } 32 | } 33 | 34 | @Override 35 | public int getItemCount() { 36 | return mAdapter.getItemCount() + 2; 37 | } 38 | 39 | @Override 40 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 41 | if(position == 0){ 42 | return; 43 | } else if(position == mAdapter.getItemCount() + 1){ 44 | return; 45 | } else{ 46 | mAdapter.onBindViewHolder(((NormalAdapter.VH)holder), position - 1); 47 | } 48 | } 49 | 50 | @Override 51 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 52 | if(viewType == ITEM_TYPE.HEADER.ordinal()){ 53 | return new RecyclerView.ViewHolder(mHeaderView) {}; 54 | } else if(viewType == ITEM_TYPE.FOOTER.ordinal()){ 55 | return new RecyclerView.ViewHolder(mFooterView) {}; 56 | } else{ 57 | return mAdapter.onCreateViewHolder(parent,viewType); 58 | } 59 | } 60 | 61 | public void addHeaderView(View view){ 62 | this.mHeaderView = view; 63 | } 64 | public void addFooterView(View view){ 65 | this.mFooterView = view; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo1/ObjectModel.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo1; 2 | 3 | public class ObjectModel { 4 | public String title; 5 | public int number; 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo2/Activity2.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo2; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.IntentFilter; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.os.Bundle; 9 | import android.widget.ListView; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | import me.xiazdong.recyclerviewdemo.R; 15 | 16 | /** 17 | * Demo2:ListView局部刷新 18 | */ 19 | public class Activity2 extends AppCompatActivity { 20 | 21 | public static final String ACTION_UPDATE_PROGRESS = "action_update_progress"; 22 | public static final String KEY_POSITION = "key_position"; 23 | public static final String KEY_PROGRESS = "key_progress"; 24 | private ListView mLv; 25 | private List mData; 26 | private DownloadAdapter mAdapter; 27 | private BroadcastReceiver mReceiver = new BroadcastReceiver() { 28 | @Override 29 | public void onReceive(Context context, Intent intent) { 30 | int position = intent.getIntExtra(KEY_POSITION, -1); 31 | int progress = intent.getIntExtra(KEY_PROGRESS, -1); 32 | if(position != -1 && progress != -1) { 33 | Job job = mData.get(position); 34 | job.progress = progress; 35 | mAdapter.notifyItemChanged(mLv, position); 36 | } 37 | } 38 | }; 39 | 40 | @Override 41 | protected void onDestroy() { 42 | super.onDestroy(); 43 | unregisterReceiver(mReceiver); 44 | } 45 | 46 | @Override 47 | protected void onCreate(Bundle savedInstanceState) { 48 | super.onCreate(savedInstanceState); 49 | setContentView(R.layout.activity_2); 50 | mLv = (ListView) findViewById(R.id.lv); 51 | mAdapter = new DownloadAdapter(this, initData()); 52 | mLv.setAdapter(mAdapter); 53 | IntentFilter filter = new IntentFilter(ACTION_UPDATE_PROGRESS); 54 | registerReceiver(mReceiver, filter); 55 | mAdapter.notifyDataSetChanged(); 56 | } 57 | List initData(){ 58 | String[] urls = this.getResources().getStringArray(R.array.download_array); 59 | mData = new ArrayList<>(); 60 | for(String url : urls){ 61 | Job job = new Job(); 62 | job.name = url.substring(0,10); 63 | job.progress = 0; 64 | job.url = url; 65 | mData.add(job); 66 | } 67 | return mData; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo2/DownloadAdapter.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo2; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | import android.util.Log; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.BaseAdapter; 10 | import android.widget.Button; 11 | import android.widget.ListView; 12 | import android.widget.ProgressBar; 13 | 14 | import com.daimajia.numberprogressbar.NumberProgressBar; 15 | 16 | import java.util.List; 17 | 18 | import me.xiazdong.recyclerviewdemo.R; 19 | 20 | /** 21 | * Created by xiazdong on 16/10/2. 22 | */ 23 | public class DownloadAdapter extends BaseAdapter{ 24 | private List mData; 25 | private Context mContext; 26 | public DownloadAdapter(Context context, List datas) { 27 | mData = datas; 28 | this.mContext = context; 29 | } 30 | 31 | @Override 32 | public int getCount() { 33 | return mData.size(); 34 | } 35 | 36 | @Override 37 | public Object getItem(int position) { 38 | return mData.get(position); 39 | } 40 | 41 | @Override 42 | public long getItemId(int position) { 43 | return position; 44 | } 45 | 46 | @Override 47 | public View getView(final int position, View convertView, ViewGroup parent) { 48 | VH holder = null; 49 | final Job job = mData.get(position); 50 | if(convertView == null){ 51 | convertView = LayoutInflater.from(mContext).inflate(R.layout.item_download,parent,false); 52 | holder = new VH(); 53 | holder.btn = (Button) convertView.findViewById(R.id.btn_download); 54 | holder.progress = (NumberProgressBar) convertView.findViewById(R.id.progress); 55 | convertView.setTag(holder); 56 | } else{ 57 | holder = (VH) convertView.getTag(); 58 | } 59 | holder.btn.setOnClickListener(new View.OnClickListener() { 60 | @Override 61 | public void onClick(View v) { 62 | new DownloadTask(mContext, position).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, job.url); 63 | } 64 | }); 65 | if(job.progress == 100){ 66 | holder.btn.setText("完成"); 67 | } else{ 68 | holder.btn.setText("下载"); 69 | } 70 | holder.progress.setProgress(job.progress); 71 | return convertView; 72 | } 73 | 74 | /** 75 | * 局部更新API 76 | */ 77 | public void notifyItemChanged(ListView listview, int position){ 78 | int firstPos = listview.getFirstVisiblePosition(); 79 | int lastPos = listview.getLastVisiblePosition(); 80 | Job job = mData.get(position); 81 | if(position >= firstPos && position <= lastPos){ 82 | View view = listview.getChildAt(position - firstPos); //NOTE 83 | DownloadAdapter.VH vh = (DownloadAdapter.VH) view.getTag(); 84 | vh.progress.setProgress(job.progress); 85 | if(job.progress == 100){ 86 | vh.btn.setText("完成"); 87 | } 88 | } 89 | } 90 | 91 | 92 | static class VH{ 93 | Button btn; 94 | NumberProgressBar progress; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo2/DownloadTask.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo2; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.AsyncTask; 6 | import android.util.Log; 7 | 8 | import java.io.ByteArrayOutputStream; 9 | import java.io.InputStream; 10 | import java.net.HttpURLConnection; 11 | import java.net.URL; 12 | 13 | /** 14 | * Created by xiazdong on 16/10/2. 15 | */ 16 | public class DownloadTask extends AsyncTask{ 17 | 18 | private Context mContext; 19 | private int position; 20 | 21 | public DownloadTask(Context context, int position) { 22 | this.mContext = context; 23 | this.position = position; 24 | } 25 | 26 | @Override 27 | protected Integer doInBackground(String... params) { 28 | URL url = null; 29 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 30 | try{ 31 | url = new URL(params[0]); 32 | HttpURLConnection con = (HttpURLConnection)url.openConnection(); 33 | con.connect(); 34 | int totalLength = con.getContentLength(); 35 | InputStream is = con.getInputStream(); 36 | byte[] buffer = new byte[1024]; 37 | int length = 0; 38 | int currentLength = 0; 39 | while((length = is.read(buffer)) != -1){ 40 | out.write(buffer,0,length); 41 | currentLength += length; 42 | int progress = (int)((((double)currentLength) / totalLength) * 100); 43 | publishProgress(progress); 44 | } 45 | } catch(Exception e){ 46 | e.printStackTrace(); 47 | } finally{ 48 | } 49 | return 100; 50 | } 51 | 52 | @Override 53 | protected void onProgressUpdate(Integer... values) { 54 | //发更新进度的广播 55 | Intent intent = new Intent(); 56 | intent.putExtra(Activity2.KEY_POSITION, position); 57 | intent.putExtra(Activity2.KEY_PROGRESS, values[0]); 58 | intent.setAction(Activity2.ACTION_UPDATE_PROGRESS); 59 | mContext.sendBroadcast(intent); 60 | } 61 | 62 | @Override 63 | protected void onPostExecute(Integer integer) { 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo2/Job.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo2; 2 | 3 | /** 4 | * 5 | * 6 | * Created by xiazdong on 16/10/1. 7 | */ 8 | public class Job { 9 | String name; 10 | String url; 11 | int progress; 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo3/Activity3.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo3; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.support.v7.widget.LinearLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.support.v7.widget.helper.ItemTouchHelper; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import me.xiazdong.recyclerviewdemo.R; 13 | import me.xiazdong.recyclerviewdemo.demo1.ObjectModel; 14 | 15 | public class Activity3 extends AppCompatActivity implements OnStartDragListener{ 16 | private RecyclerView mRv; 17 | private NormalAdapter mAdapter; 18 | private ItemTouchHelper mHelper; 19 | private List mData; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_3); 25 | mRv = (RecyclerView) findViewById(R.id.rv); 26 | mRv.setLayoutManager(new LinearLayoutManager(this)); 27 | mAdapter = new NormalAdapter(mData = initData(), this); 28 | mRv.setAdapter(mAdapter); 29 | mHelper = new ItemTouchHelper(new SimpleItemTouchCallback(mAdapter, mData)); 30 | mHelper.attachToRecyclerView(mRv); 31 | 32 | } 33 | 34 | public ArrayList initData(){ 35 | ArrayList models = new ArrayList<>(); 36 | String[] titles = getResources().getStringArray(R.array.title_array); 37 | for(int i=0;i{ 17 | 18 | private List mDatas; 19 | private OnStartDragListener mListener; 20 | public NormalAdapter(List data, OnStartDragListener listener) { 21 | this.mDatas = data; 22 | mListener = listener; 23 | } 24 | 25 | @Override 26 | public void onBindViewHolder(final VH holder, int position) { 27 | ObjectModel model = mDatas.get(position); 28 | holder.title.setText(model.title); 29 | holder.number.setOnTouchListener(new View.OnTouchListener() { 30 | @Override 31 | public boolean onTouch(View v, MotionEvent event) { 32 | if(event.getAction() == MotionEvent.ACTION_DOWN){ 33 | mListener.startDrag(holder); 34 | } 35 | return false; 36 | } 37 | }); 38 | } 39 | 40 | @Override 41 | public int getItemCount() { 42 | return mDatas.size(); 43 | } 44 | 45 | @Override 46 | public VH onCreateViewHolder(ViewGroup parent, int viewType) { 47 | View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_3, parent, false); 48 | return new VH(v); 49 | } 50 | 51 | public static class VH extends RecyclerView.ViewHolder{ 52 | public final TextView title; 53 | public final ImageView number; 54 | public VH(View v) { 55 | super(v); 56 | title = (TextView) v.findViewById(R.id.title); 57 | number = (ImageView) v.findViewById(R.id.number); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo3/SimpleItemTouchCallback.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo3; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.support.v7.widget.helper.ItemTouchHelper; 5 | import android.util.Log; 6 | 7 | import java.util.Collections; 8 | import java.util.List; 9 | 10 | import me.xiazdong.recyclerviewdemo.demo1.ObjectModel; 11 | 12 | /** 13 | * Created by xiazdong on 16/10/6. 14 | */ 15 | public class SimpleItemTouchCallback extends ItemTouchHelper.Callback { 16 | 17 | private NormalAdapter mAdapter; 18 | private List mData; 19 | public SimpleItemTouchCallback(NormalAdapter adapter, List data){ 20 | mAdapter = adapter; 21 | mData = data; 22 | } 23 | /** 24 | * 设置支持的拖拽、滑动的方向 25 | */ 26 | @Override 27 | public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 28 | int dragFlag = ItemTouchHelper.UP | ItemTouchHelper.DOWN; 29 | int swipeFlag = ItemTouchHelper.START | ItemTouchHelper.END; 30 | return makeMovementFlags(dragFlag,swipeFlag); 31 | } 32 | 33 | @Override 34 | public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { 35 | int from = viewHolder.getAdapterPosition(); 36 | int to = target.getAdapterPosition(); 37 | Collections.swap(mData, from, to); 38 | mAdapter.notifyItemMoved(from, to); 39 | return true; 40 | } 41 | 42 | @Override 43 | public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { 44 | int pos = viewHolder.getAdapterPosition(); 45 | mData.remove(pos); 46 | mAdapter.notifyItemRemoved(pos); 47 | } 48 | 49 | 50 | /** 51 | * 状态改变时回调 52 | */ 53 | @Override 54 | public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { 55 | super.onSelectedChanged(viewHolder, actionState); 56 | Log.i("Callback", actionState + ""); 57 | if(actionState != ItemTouchHelper.ACTION_STATE_IDLE){ 58 | NormalAdapter.VH holder = (NormalAdapter.VH)viewHolder; 59 | holder.itemView.setBackgroundColor(0xffbcbcbc); 60 | } 61 | } 62 | 63 | /** 64 | * 拖拽或滑动完成之后调用,用来清除一些状态 65 | */ 66 | @Override 67 | public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 68 | super.clearView(recyclerView, viewHolder); 69 | NormalAdapter.VH holder = (NormalAdapter.VH)viewHolder; 70 | holder.itemView.setBackgroundColor(0xffeeeeee); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo4/Activity4.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo4; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.support.v7.widget.LinearLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.support.v7.widget.SimpleItemAnimator; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import me.xiazdong.recyclerviewdemo.R; 13 | import me.xiazdong.recyclerviewdemo.demo1.DividerItemDecoration; 14 | 15 | 16 | /** 17 | * 坑:RecyclerView局部更新时,闪屏 18 | */ 19 | public class Activity4 extends AppCompatActivity { 20 | 21 | private RecyclerView mRv; 22 | private List mData; 23 | private ImageAdapter mAdapter; 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_4); 28 | mRv = (RecyclerView) findViewById(R.id.rv); 29 | mData = initData(); 30 | mRv.setLayoutManager(new LinearLayoutManager(this)); 31 | mAdapter = new ImageAdapter(mData); 32 | //((SimpleItemAnimator)mRv.getItemAnimator()).setSupportsChangeAnimations(false); 33 | mRv.setAdapter(mAdapter); 34 | mRv.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST)); 35 | } 36 | 37 | 38 | public List initData(){ 39 | List list = new ArrayList<>(); 40 | for(int i = 0; i < 10; i++){ 41 | Image image = new Image(); 42 | image.id = R.drawable.bg; 43 | image.name = "bg"; 44 | list.add(image); 45 | } 46 | return list; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo4/Image.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo4; 2 | 3 | /** 4 | * Created by xiazdong on 16/10/6. 5 | */ 6 | public class Image { 7 | String name; 8 | int id; 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo4/ImageAdapter.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo4; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.util.Log; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | import java.util.List; 12 | 13 | import me.xiazdong.recyclerviewdemo.R; 14 | 15 | /** 16 | * Created by xiazdong on 16/10/6. 17 | */ 18 | public class ImageAdapter extends RecyclerView.Adapter{ 19 | 20 | private List mData; 21 | 22 | public ImageAdapter(List data) { 23 | this.mData = data; 24 | } 25 | 26 | @Override 27 | public void onBindViewHolder(final VH holder, final int position) { 28 | final Image image = mData.get(position); 29 | holder.mText.setText(image.name); 30 | holder.mImage.setImageResource(image.id); 31 | holder.itemView.setOnClickListener(new View.OnClickListener() { 32 | @Override 33 | public void onClick(View v) { 34 | image.name = "haha"; 35 | notifyItemChanged(position); 36 | } 37 | }); 38 | } 39 | 40 | @Override 41 | public VH onCreateViewHolder(ViewGroup parent, int viewType) { 42 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_4, parent ,false); 43 | return new VH(view); 44 | } 45 | 46 | @Override 47 | public int getItemCount() { 48 | return mData.size(); 49 | } 50 | 51 | static class VH extends RecyclerView.ViewHolder{ 52 | 53 | private ImageView mImage; 54 | private TextView mText; 55 | 56 | public VH(View itemView) { 57 | super(itemView); 58 | mImage = (ImageView) itemView.findViewById(R.id.image); 59 | mText = (TextView) itemView.findViewById(R.id.name); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo5/Activity5.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo5; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.support.v7.widget.LinearLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.view.LayoutInflater; 8 | import android.view.Menu; 9 | import android.view.MenuInflater; 10 | import android.view.MenuItem; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | import me.xiazdong.recyclerviewdemo.R; 18 | import me.xiazdong.recyclerviewdemo.demo1.ObjectModel; 19 | 20 | /** 21 | * RecyclerView实现setEmptyView() 22 | */ 23 | public class Activity5 extends AppCompatActivity { 24 | private EmptyRecyclerView mRv; 25 | private List mData; 26 | private NormalAdapter mAdapter; 27 | 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_5); 33 | mRv = (EmptyRecyclerView) findViewById(R.id.rv); 34 | mRv.setLayoutManager(new LinearLayoutManager(this)); 35 | mData = new ArrayList<>(); 36 | mAdapter = new NormalAdapter(mData); 37 | //View view = LayoutInflater.from(this).inflate(R.layout.empty, null); 38 | View view = findViewById(R.id.text_empty); 39 | mRv.setEmptyView(view); 40 | mRv.setAdapter(mAdapter); 41 | } 42 | 43 | 44 | @Override 45 | public boolean onCreateOptionsMenu(Menu menu) { 46 | getMenuInflater().inflate(R.menu.menu_5, menu); 47 | return true; 48 | } 49 | 50 | @Override 51 | public boolean onOptionsItemSelected(MenuItem item) { 52 | switch (item.getItemId()){ 53 | case R.id.item_add: 54 | mData.add(0,"hello"); 55 | mAdapter.notifyItemInserted(0); 56 | break; 57 | case R.id.item_delete: 58 | if(!mData.isEmpty()) { 59 | mData.remove(0); 60 | mAdapter.notifyItemRemoved(0); 61 | } 62 | break; 63 | } 64 | 65 | return super.onOptionsItemSelected(item); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo5/EmptyRecyclerView.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo5; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.util.AttributeSet; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | /** 11 | * Created by xiazdong on 16/10/7. 12 | */ 13 | public class EmptyRecyclerView extends RecyclerView{ 14 | 15 | private View mEmptyView; 16 | 17 | private AdapterDataObserver mObserver = new AdapterDataObserver() { 18 | @Override 19 | public void onChanged() { 20 | Adapter adapter = getAdapter(); 21 | if(adapter.getItemCount() == 0){ 22 | mEmptyView.setVisibility(VISIBLE); 23 | EmptyRecyclerView.this.setVisibility(GONE); 24 | } else{ 25 | mEmptyView.setVisibility(GONE); 26 | EmptyRecyclerView.this.setVisibility(VISIBLE); 27 | } 28 | } 29 | 30 | @Override 31 | public void onItemRangeChanged(int positionStart, int itemCount) { 32 | onChanged(); 33 | } 34 | 35 | @Override 36 | public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { 37 | onChanged(); 38 | } 39 | 40 | @Override 41 | public void onItemRangeRemoved(int positionStart, int itemCount) { 42 | onChanged(); 43 | } 44 | 45 | @Override 46 | public void onItemRangeInserted(int positionStart, int itemCount) { 47 | onChanged(); 48 | } 49 | 50 | @Override 51 | public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { 52 | onChanged(); 53 | } 54 | }; 55 | 56 | public EmptyRecyclerView(Context context, @Nullable AttributeSet attrs) { 57 | super(context, attrs); 58 | } 59 | 60 | public void setEmptyView(View view){ 61 | mEmptyView = view; 62 | } 63 | 64 | public void setAdapter(RecyclerView.Adapter adapter){ 65 | super.setAdapter(adapter); 66 | adapter.registerAdapterDataObserver(mObserver); 67 | mObserver.onChanged(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo5/NormalAdapter.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo5; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.TextView; 8 | 9 | import java.util.List; 10 | 11 | import me.xiazdong.recyclerviewdemo.R; 12 | import me.xiazdong.recyclerviewdemo.demo1.ObjectModel; 13 | 14 | public class NormalAdapter extends RecyclerView.Adapter{ 15 | 16 | private List mDatas; 17 | public NormalAdapter(List data) { 18 | this.mDatas = data; 19 | } 20 | 21 | @Override 22 | public void onBindViewHolder(VH holder, int position) { 23 | holder.title.setText(mDatas.get(position)); 24 | } 25 | 26 | @Override 27 | public int getItemCount() { 28 | return mDatas.size(); 29 | } 30 | 31 | @Override 32 | public VH onCreateViewHolder(ViewGroup parent, int viewType) { 33 | View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_5, parent, false); 34 | return new VH(v); 35 | } 36 | 37 | public static class VH extends RecyclerView.ViewHolder{ 38 | public final TextView title; 39 | public VH(View v) { 40 | super(v); 41 | title = (TextView) v.findViewById(R.id.text); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo6/Activity6.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo6; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.support.v7.widget.SimpleItemAnimator; 7 | import android.support.v7.widget.StaggeredGridLayoutManager; 8 | import android.support.v7.widget.Toolbar; 9 | import android.widget.ImageView; 10 | 11 | import com.squareup.picasso.Picasso; 12 | 13 | import java.util.ArrayList; 14 | import java.util.Arrays; 15 | import java.util.List; 16 | 17 | import me.xiazdong.recyclerviewdemo.R; 18 | 19 | /** 20 | * RecyclerView实现瀑布流 21 | * 22 | * 由于该例子比较简单,因此顺便介绍万能Adapter方案 23 | */ 24 | public class Activity6 extends AppCompatActivity { 25 | private RecyclerView mRv; 26 | private QuickAdapter mAdapter; 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_6); 31 | 32 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 33 | setSupportActionBar(toolbar); 34 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 35 | 36 | mRv = (RecyclerView) findViewById(R.id.rv); 37 | mRv.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)); 38 | mAdapter = new QuickAdapter(initData()) { 39 | @Override 40 | public int getLayoutId(int viewType) { 41 | return R.layout.item_6; 42 | } 43 | 44 | @Override 45 | public void convert(VH holder, Integer data, int position) { 46 | ImageView imageView = holder.getView(R.id.image); 47 | Picasso.with(Activity6.this).load(data).into(imageView); 48 | //holder.itemView.setOnClickListener(); 此处添加点击事件 49 | } 50 | 51 | @Override 52 | public int getItemViewType(int position) { 53 | return super.getItemViewType(position); 54 | } 55 | }; 56 | mAdapter.setHasStableIds(true); 57 | ((SimpleItemAnimator)mRv.getItemAnimator()).setSupportsChangeAnimations(false); 58 | mRv.setAdapter(mAdapter); 59 | 60 | } 61 | 62 | public List initData(){ 63 | Integer[] images = {R.drawable.s1, R.drawable.s2, R.drawable.s3, R.drawable.s4, R.drawable.s5, 64 | R.drawable.s6, R.drawable.s7, R.drawable.s8, R.drawable.s9, R.drawable.s10 65 | }; 66 | ArrayList list = new ArrayList<>(); 67 | for(int i=0;i<2;i++){ 68 | for(Integer image:images){ 69 | list.add(image); 70 | } 71 | } 72 | return list; 73 | } 74 | 75 | 76 | 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/me/xiazdong/recyclerviewdemo/demo6/QuickAdapter.java: -------------------------------------------------------------------------------- 1 | package me.xiazdong.recyclerviewdemo.demo6; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.util.SparseArray; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by xiazdong on 16/10/12. 14 | */ 15 | public abstract class QuickAdapter extends RecyclerView.Adapter{ 16 | 17 | private List mDatas; 18 | 19 | public QuickAdapter(List datas){ 20 | this.mDatas = datas; 21 | } 22 | 23 | public abstract int getLayoutId(int viewType); 24 | 25 | @Override 26 | public VH onCreateViewHolder(ViewGroup parent, int viewType) { 27 | return VH.get(parent,getLayoutId(viewType)); 28 | } 29 | 30 | @Override 31 | public void onBindViewHolder(VH holder, int position) { 32 | convert(holder, mDatas.get(position), position); 33 | } 34 | 35 | @Override 36 | public int getItemCount() { 37 | return mDatas.size(); 38 | } 39 | 40 | public abstract void convert(VH holder, T data, int position); 41 | 42 | static class VH extends RecyclerView.ViewHolder{ 43 | private SparseArray mViews; 44 | private View mConvertView; 45 | 46 | private VH(View v){ 47 | super(v); 48 | mConvertView = v; 49 | mViews = new SparseArray<>(); 50 | } 51 | 52 | public static VH get(ViewGroup parent, int layoutId){ 53 | View convertView = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false); 54 | return new VH(convertView); 55 | } 56 | 57 | public T getView(int id){ 58 | View v = mViews.get(id); 59 | if(v == null){ 60 | v = mConvertView.findViewById(id); 61 | mViews.put(id, v); 62 | } 63 | return (T)v; 64 | } 65 | 66 | public void setText(int id, String value){ 67 | TextView view = getView(id); 68 | view.setText(value); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/res/assets/demo6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/assets/demo6.gif -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/drawable/bg.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/divider.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/drawable/divider.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/item1_divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/s1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/drawable/s1.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/s10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/drawable/s10.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/s2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/drawable/s2.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/s3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/drawable/s3.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/s4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/drawable/s4.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/s5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/drawable/s5.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/s6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/drawable/s6.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/s7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/drawable/s7.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/s8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/drawable/s8.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/s9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/RecyclerViewDemo/645bd1ea4be68dabca6c814c4ffe1cc078329cfc/app/src/main/res/drawable/s9.jpg -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 17 | 25 | 26 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_6.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 24 | 33 | 40 | 41 | 42 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_7.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 |