简单RecyclerView入门
来源:互联网 发布:音频矩阵和视频矩阵 编辑:程序博客网 时间:2024/05/29 18:12
compile 'com.android.support:recyclerview-v7:25.2.0'
RecyclerView依赖跟版本一致简单介绍
http://blog.csdn.net/lmj623565791/article/details/45059587
添加分割线
http://www.jianshu.com/p/4eff036360da
动画
http://blog.csdn.net/hongtao_studio/article/details/50733118
http://m.blog.csdn.net/article/details?id=53392877
//添加依赖
https://github.com/wasabeef/recyclerview-animators
import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.View;import android.widget.Toast;import java.util.ArrayList;public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private ArrayList<String> list=new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //找控件 recyclerView = (RecyclerView) findViewById(R.id.recyclerview); //布局管理器 LinearLayoutManager layoutManager=new LinearLayoutManager(this); //添加 recyclerView.setLayoutManager(layoutManager); //分割线 MyDecoration myDecoration=new MyDecoration(this,MyDecoration.VERTICAL_LIST); //添加分割线 recyclerView.addItemDecoration(myDecoration); //数据 getDat(); } private void getDat() { for (int i=0;i<50;i++){ list.add("条目"+i); } //适配器 final MyAdapter myAdapter = new MyAdapter(this, list); //添加适配器 recyclerView.setAdapter(myAdapter); //点击事件 myAdapter.setOnItemclick(new MyAdapter.OnItemclick() { @Override public void onItemclick(View view, int position) { Toast.makeText(MainActivity.this, "条目的点击监听:" + position, Toast.LENGTH_SHORT).show(); //添加动画 MyItemAnimator animator = new MyItemAnimator(); //添加动画时间 animator.setAddDuration(2000); myAdapter.add(position, "新的添加的条目"); recyclerView.setItemAnimator(animator); //移动动画时间 animator.setMoveDuration(2000); } }); //长按事件 myAdapter.setOnItemlongclick(new MyAdapter.OnItemlongclick() { @Override public void onItemlongclick(View view, int position) { Toast.makeText(MainActivity.this, "条目的长按监听:" + position, Toast.LENGTH_SHORT).show(); //删除动画 MyItemAnimator animator = new MyItemAnimator(); //删除动画时间 animator.setRemoveDuration(2000); myAdapter.remove(position); recyclerView.setItemAnimator(animator); //移动动画时间 animator.setMoveDuration(2000); } }); }}main布局
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.v7.widget.RecyclerView android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent"></android.support.v7.widget.RecyclerView></RelativeLayout>
适配器
import android.app.Activity;import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;import java.util.List;/** * 类的用途: * * @name 姜军 * @time 2017/4/14 13:38 */public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { private Context context; private List<String> list; public MyAdapter(Context context, List<String> list) { this.context = context; this.list = list; } //定义接口 public OnItemclick onItemclick; public OnItemlongclick onItemlongclick; //定义点击事件 public interface OnItemclick{ void onItemclick(View view,int position); } //定义长按监听 public interface OnItemlongclick{ void onItemlongclick(View view,int position); } //提供点击事件set方法 public void setOnItemclick(OnItemclick onItemclick) { this.onItemclick = onItemclick; } //提供长按监听set方法 public void setOnItemlongclick(OnItemlongclick onItemlongclick) { this.onItemlongclick = onItemlongclick; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //获取布局 View view=View.inflate(context, R.layout.item,null); //获取item final MyViewHolder holder=new MyViewHolder(view); //获取屏幕宽 int width =((Activity)context).getWindow().getWindowManager().getDefaultDisplay().getWidth(); //赋值屏幕宽 parent.getLayoutParams().width=width; //点击事件 view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //判断接口不位空 if (onItemclick!=null){ //获取position int position = holder.getLayoutPosition(); //传值 onItemclick.onItemclick(v,position); } } }); //长按事件 view.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { //判断接口不位空 if (onItemlongclick!=null){ //获取position int position = holder.getLayoutPosition(); //传值 onItemlongclick.onItemlongclick(v,position); } //事件消费 return true; } }); //返回item return holder; } @Override public void onBindViewHolder(MyViewHolder holder, int position) { holder.text.setText(list.get(position)); } @Override public int getItemCount() { return list.size(); } public class MyViewHolder extends RecyclerView.ViewHolder{ private final TextView text; private final ImageView imageView; public MyViewHolder(View itemView) { super(itemView); text = (TextView) itemView.findViewById(R.id.text); imageView = (ImageView) itemView.findViewById(R.id.image); } } //添加数据 public void add(int position, String text) { list.add(position, text); notifyItemInserted(position); } //移除数据 public void remove(int position) { list.remove(position); notifyItemRemoved(position); } //改变数据 public void change(int position, String text) { list.remove(position); list.add(position, text); notifyItemChanged(position); }}布局
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/text" android:textColor="@android:color/background_dark" android:textSize="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /><ImageView android:id="@+id/image" android:background="@mipmap/ic_launcher" android:layout_width="50dp" android:layout_height="50dp" /></LinearLayout>
动画
/* * 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. */import android.support.annotation.NonNull;import android.support.v4.animation.AnimatorCompatHelper;import android.support.v4.view.ViewCompat;import android.support.v4.view.ViewPropertyAnimatorCompat;import android.support.v4.view.ViewPropertyAnimatorListener;import android.support.v7.widget.RecyclerView.ViewHolder;import android.support.v7.widget.SimpleItemAnimator;import android.view.View;import java.util.ArrayList;import java.util.List;public class MyItemAnimator extends SimpleItemAnimator { private static final boolean DEBUG = false; private ArrayList<ViewHolder> mPendingRemovals = new ArrayList<>(); private ArrayList<ViewHolder> mPendingAdditions = new ArrayList<>(); private ArrayList<MoveInfo> mPendingMoves = new ArrayList<>(); private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>(); ArrayList<ArrayList<ViewHolder>> mAdditionsList = new ArrayList<>(); ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>(); ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<>(); ArrayList<ViewHolder> mAddAnimations = new ArrayList<>(); ArrayList<ViewHolder> mMoveAnimations = new ArrayList<>(); ArrayList<ViewHolder> mRemoveAnimations = new ArrayList<>(); ArrayList<ViewHolder> mChangeAnimations = new ArrayList<>(); private static class MoveInfo { public ViewHolder holder; public int fromX, fromY, toX, toY; MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) { this.holder = holder; this.fromX = fromX; this.fromY = fromY; this.toX = toX; this.toY = toY; } } private static class ChangeInfo { public ViewHolder oldHolder, newHolder; public int fromX, fromY, toX, toY; private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder) { this.oldHolder = oldHolder; this.newHolder = newHolder; } ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder, int fromX, int fromY, int toX, int toY) { this(oldHolder, newHolder); this.fromX = fromX; this.fromY = fromY; this.toX = toX; this.toY = toY; } @Override public String toString() { return "ChangeInfo{" + "oldHolder=" + oldHolder + ", newHolder=" + newHolder + ", fromX=" + fromX + ", fromY=" + fromY + ", toX=" + toX + ", toY=" + toY + '}'; } } @Override public void runPendingAnimations() { boolean removalsPending = !mPendingRemovals.isEmpty(); boolean movesPending = !mPendingMoves.isEmpty(); boolean changesPending = !mPendingChanges.isEmpty(); boolean additionsPending = !mPendingAdditions.isEmpty(); if (!removalsPending && !movesPending && !additionsPending && !changesPending) { // nothing to animate return; } // First, remove stuff for (ViewHolder holder : mPendingRemovals) { animateRemoveImpl(holder); } mPendingRemovals.clear(); // Next, move stuff if (movesPending) { final ArrayList<MoveInfo> moves = new ArrayList<>(); moves.addAll(mPendingMoves); mMovesList.add(moves); mPendingMoves.clear(); Runnable mover = new Runnable() { @Override public void run() { for (MoveInfo moveInfo : moves) { animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, moveInfo.toX, moveInfo.toY); } moves.clear(); mMovesList.remove(moves); } }; if (removalsPending) { View view = moves.get(0).holder.itemView; ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration()); } else { mover.run(); } } // Next, change stuff, to run in parallel with move animations if (changesPending) { final ArrayList<ChangeInfo> changes = new ArrayList<>(); changes.addAll(mPendingChanges); mChangesList.add(changes); mPendingChanges.clear(); Runnable changer = new Runnable() { @Override public void run() { for (ChangeInfo change : changes) { animateChangeImpl(change); } changes.clear(); mChangesList.remove(changes); } }; if (removalsPending) { ViewHolder holder = changes.get(0).oldHolder; ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration()); } else { changer.run(); } } // Next, add stuff if (additionsPending) { final ArrayList<ViewHolder> additions = new ArrayList<>(); additions.addAll(mPendingAdditions); mAdditionsList.add(additions); mPendingAdditions.clear(); Runnable adder = new Runnable() { @Override public void run() { for (ViewHolder holder : additions) { animateAddImpl(holder); } additions.clear(); mAdditionsList.remove(additions); } }; if (removalsPending || movesPending || changesPending) { long removeDuration = removalsPending ? getRemoveDuration() : 0; long moveDuration = movesPending ? getMoveDuration() : 0; long changeDuration = changesPending ? getChangeDuration() : 0; long totalDelay = removeDuration + Math.max(moveDuration, changeDuration); View view = additions.get(0).itemView; ViewCompat.postOnAnimationDelayed(view, adder, totalDelay); } else { adder.run(); } } } @Override public boolean animateRemove(final ViewHolder holder) { resetAnimation(holder); mPendingRemovals.add(holder); return true; } private void animateRemoveImpl(final ViewHolder holder) { final View view = holder.itemView;//首先得到ItemView final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);//开启一个属性动画 mRemoveAnimations.add(holder);//加入到要删除的VIew中 animation.setDuration(getRemoveDuration())//设置延迟时间 .translationX(view.getWidth()).setListener(new VpaListenerAdapter() {//listener是开始和结束的监听 @Override public void onAnimationStart(View view) { dispatchRemoveStarting(holder); } @Override public void onAnimationEnd(View view) { animation.setListener(null);//当动画结束的时候要将监听置为空 //ViewCompat.setAlpha(view, 1);//因为有复用布局的问题,所以你将控件删除的时候需要将他还原,要不会出现重复问题 ViewCompat.setTranslationX(view,0);//因为有复用布局的问题,所以你将控件删除的时候需要将他还原,要不会出现重复问题 dispatchRemoveFinished(holder); mRemoveAnimations.remove(holder); dispatchFinishedWhenDone(); } }).start(); } @Override public boolean animateAdd(final ViewHolder holder) { resetAnimation(holder); //ViewCompat.setAlpha(holder.itemView, 0); ViewCompat.setTranslationX(holder.itemView,-holder.itemView.getWidth()); mPendingAdditions.add(holder); return true; } void animateAddImpl(final ViewHolder holder) { final View view = holder.itemView; final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view); mAddAnimations.add(holder); //animation.alpha(1).setDuration(getAddDuration()). animation.translationX(0).setDuration(getAddDuration()). setListener(new VpaListenerAdapter() { @Override public void onAnimationStart(View view) { dispatchAddStarting(holder); } @Override public void onAnimationCancel(View view) { ViewCompat.setAlpha(view, 1); } @Override public void onAnimationEnd(View view) { animation.setListener(null); dispatchAddFinished(holder); mAddAnimations.remove(holder); dispatchFinishedWhenDone(); } }).start(); } @Override public boolean animateMove(final ViewHolder holder, int fromX, int fromY, int toX, int toY) { final View view = holder.itemView; fromX += ViewCompat.getTranslationX(holder.itemView); fromY += ViewCompat.getTranslationY(holder.itemView); resetAnimation(holder); int deltaX = toX - fromX; int deltaY = toY - fromY; if (deltaX == 0 && deltaY == 0) { dispatchMoveFinished(holder); return false; } if (deltaX != 0) { ViewCompat.setTranslationX(view, -deltaX); } if (deltaY != 0) { ViewCompat.setTranslationY(view, -deltaY); } mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); return true; } void animateMoveImpl(final ViewHolder holder, int fromX, int fromY, int toX, int toY) { final View view = holder.itemView; final int deltaX = toX - fromX; final int deltaY = toY - fromY; if (deltaX != 0) { ViewCompat.animate(view).translationX(0); } if (deltaY != 0) { ViewCompat.animate(view).translationY(0); } // TODO: make EndActions end listeners instead, since end actions aren't called when // vpas are canceled (and can't end them. why?) // need listener functionality in VPACompat for this. Ick. final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view); animation.rotationXBy(180); mMoveAnimations.add(holder); animation.setDuration(getMoveDuration()).setListener(new VpaListenerAdapter() { @Override public void onAnimationStart(View view) { dispatchMoveStarting(holder); } @Override public void onAnimationCancel(View view) { if (deltaX != 0) { ViewCompat.setTranslationX(view, 0); } if (deltaY != 0) { ViewCompat.setTranslationY(view, 0); } } @Override public void onAnimationEnd(View view) { animation.setListener(null); ViewCompat.setRotationX(view,0); dispatchMoveFinished(holder); mMoveAnimations.remove(holder); dispatchFinishedWhenDone(); } }).start(); } @Override public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, int fromX, int fromY, int toX, int toY) { if (oldHolder == newHolder) { // Don't know how to run change animations when the same view holder is re-used. // run a move animation to handle position changes. return animateMove(oldHolder, fromX, fromY, toX, toY); } final float prevTranslationX = ViewCompat.getTranslationX(oldHolder.itemView); final float prevTranslationY = ViewCompat.getTranslationY(oldHolder.itemView); final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView); resetAnimation(oldHolder); int deltaX = (int) (toX - fromX - prevTranslationX); int deltaY = (int) (toY - fromY - prevTranslationY); // recover prev translation state after ending animation ViewCompat.setTranslationX(oldHolder.itemView, prevTranslationX); ViewCompat.setTranslationY(oldHolder.itemView, prevTranslationY); ViewCompat.setAlpha(oldHolder.itemView, prevAlpha); if (newHolder != null) { // carry over translation values resetAnimation(newHolder); ViewCompat.setTranslationX(newHolder.itemView, -deltaX); ViewCompat.setTranslationY(newHolder.itemView, -deltaY); //ViewCompat.setAlpha(newHolder.itemView, 0); //新的移除视线 ViewCompat.setTranslationX(newHolder.itemView,-newHolder.itemView.getWidth()); } mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY)); return true; } void animateChangeImpl(final ChangeInfo changeInfo) { final ViewHolder holder = changeInfo.oldHolder; final View view = holder == null ? null : holder.itemView; final ViewHolder newHolder = changeInfo.newHolder; final View newView = newHolder != null ? newHolder.itemView : null; if (view != null) { final ViewPropertyAnimatorCompat oldViewAnim = ViewCompat.animate(view).setDuration( getChangeDuration()); mChangeAnimations.add(changeInfo.oldHolder); oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX); oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY); //oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() { //老的移除 oldViewAnim.translationX(view.getWidth()).setListener(new VpaListenerAdapter() { @Override public void onAnimationStart(View view) { dispatchChangeStarting(changeInfo.oldHolder, true); } @Override public void onAnimationEnd(View view) { oldViewAnim.setListener(null); ViewCompat.setAlpha(view, 1); ViewCompat.setTranslationX(view, 0); ViewCompat.setTranslationY(view, 0); dispatchChangeFinished(changeInfo.oldHolder, true); mChangeAnimations.remove(changeInfo.oldHolder); dispatchFinishedWhenDone(); } }).start(); } if (newView != null) { final ViewPropertyAnimatorCompat newViewAnimation = ViewCompat.animate(newView); mChangeAnimations.add(changeInfo.newHolder); newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()). alpha(1).setListener(new VpaListenerAdapter() { @Override public void onAnimationStart(View view) { dispatchChangeStarting(changeInfo.newHolder, false); } @Override public void onAnimationEnd(View view) { newViewAnimation.setListener(null); ViewCompat.setAlpha(newView, 1); ViewCompat.setTranslationX(newView, 0); ViewCompat.setTranslationY(newView, 0); dispatchChangeFinished(changeInfo.newHolder, false); mChangeAnimations.remove(changeInfo.newHolder); dispatchFinishedWhenDone(); } }).start(); } } private void endChangeAnimation(List<ChangeInfo> infoList, ViewHolder item) { for (int i = infoList.size() - 1; i >= 0; i--) { ChangeInfo changeInfo = infoList.get(i); if (endChangeAnimationIfNecessary(changeInfo, item)) { if (changeInfo.oldHolder == null && changeInfo.newHolder == null) { infoList.remove(changeInfo); } } } } private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) { if (changeInfo.oldHolder != null) { endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder); } if (changeInfo.newHolder != null) { endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder); } } private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, ViewHolder item) { boolean oldItem = false; if (changeInfo.newHolder == item) { changeInfo.newHolder = null; } else if (changeInfo.oldHolder == item) { changeInfo.oldHolder = null; oldItem = true; } else { return false; } ViewCompat.setAlpha(item.itemView, 1); ViewCompat.setTranslationX(item.itemView, 0); ViewCompat.setTranslationY(item.itemView, 0); dispatchChangeFinished(item, oldItem); return true; } @Override public void endAnimation(ViewHolder item) { final View view = item.itemView; // this will trigger end callback which should set properties to their target values. ViewCompat.animate(view).cancel(); // TODO if some other animations are chained to end, how do we cancel them as well? for (int i = mPendingMoves.size() - 1; i >= 0; i--) { MoveInfo moveInfo = mPendingMoves.get(i); if (moveInfo.holder == item) { ViewCompat.setTranslationY(view, 0); ViewCompat.setTranslationX(view, 0); dispatchMoveFinished(item); mPendingMoves.remove(i); } } endChangeAnimation(mPendingChanges, item); if (mPendingRemovals.remove(item)) { ViewCompat.setAlpha(view, 1); dispatchRemoveFinished(item); } if (mPendingAdditions.remove(item)) { ViewCompat.setAlpha(view, 1); dispatchAddFinished(item); } for (int i = mChangesList.size() - 1; i >= 0; i--) { ArrayList<ChangeInfo> changes = mChangesList.get(i); endChangeAnimation(changes, item); if (changes.isEmpty()) { mChangesList.remove(i); } } for (int i = mMovesList.size() - 1; i >= 0; i--) { ArrayList<MoveInfo> moves = mMovesList.get(i); for (int j = moves.size() - 1; j >= 0; j--) { MoveInfo moveInfo = moves.get(j); if (moveInfo.holder == item) { ViewCompat.setTranslationY(view, 0); ViewCompat.setTranslationX(view, 0); dispatchMoveFinished(item); moves.remove(j); if (moves.isEmpty()) { mMovesList.remove(i); } break; } } } for (int i = mAdditionsList.size() - 1; i >= 0; i--) { ArrayList<ViewHolder> additions = mAdditionsList.get(i); if (additions.remove(item)) { ViewCompat.setAlpha(view, 1); dispatchAddFinished(item); if (additions.isEmpty()) { mAdditionsList.remove(i); } } } // animations should be ended by the cancel above. //noinspection PointlessBooleanExpression,ConstantConditions if (mRemoveAnimations.remove(item) && DEBUG) { throw new IllegalStateException("after animation is cancelled, item should not be in " + "mRemoveAnimations list"); } //noinspection PointlessBooleanExpression,ConstantConditions if (mAddAnimations.remove(item) && DEBUG) { throw new IllegalStateException("after animation is cancelled, item should not be in " + "mAddAnimations list"); } //noinspection PointlessBooleanExpression,ConstantConditions if (mChangeAnimations.remove(item) && DEBUG) { throw new IllegalStateException("after animation is cancelled, item should not be in " + "mChangeAnimations list"); } //noinspection PointlessBooleanExpression,ConstantConditions if (mMoveAnimations.remove(item) && DEBUG) { throw new IllegalStateException("after animation is cancelled, item should not be in " + "mMoveAnimations list"); } dispatchFinishedWhenDone(); } private void resetAnimation(ViewHolder holder) { AnimatorCompatHelper.clearInterpolator(holder.itemView); endAnimation(holder); } @Override public boolean isRunning() { return (!mPendingAdditions.isEmpty() || !mPendingChanges.isEmpty() || !mPendingMoves.isEmpty() || !mPendingRemovals.isEmpty() || !mMoveAnimations.isEmpty() || !mRemoveAnimations.isEmpty() || !mAddAnimations.isEmpty() || !mChangeAnimations.isEmpty() || !mMovesList.isEmpty() || !mAdditionsList.isEmpty() || !mChangesList.isEmpty()); } /** * Check the state of currently pending and running animations. If there are none * pending/running, call {@link #dispatchAnimationsFinished()} to notify any * listeners. */ void dispatchFinishedWhenDone() { if (!isRunning()) { dispatchAnimationsFinished(); } } @Override public void endAnimations() { int count = mPendingMoves.size(); for (int i = count - 1; i >= 0; i--) { MoveInfo item = mPendingMoves.get(i); View view = item.holder.itemView; ViewCompat.setTranslationY(view, 0); ViewCompat.setTranslationX(view, 0); dispatchMoveFinished(item.holder); mPendingMoves.remove(i); } count = mPendingRemovals.size(); for (int i = count - 1; i >= 0; i--) { ViewHolder item = mPendingRemovals.get(i); dispatchRemoveFinished(item); mPendingRemovals.remove(i); } count = mPendingAdditions.size(); for (int i = count - 1; i >= 0; i--) { ViewHolder item = mPendingAdditions.get(i); View view = item.itemView; ViewCompat.setAlpha(view, 1); dispatchAddFinished(item); mPendingAdditions.remove(i); } count = mPendingChanges.size(); for (int i = count - 1; i >= 0; i--) { endChangeAnimationIfNecessary(mPendingChanges.get(i)); } mPendingChanges.clear(); if (!isRunning()) { return; } int listCount = mMovesList.size(); for (int i = listCount - 1; i >= 0; i--) { ArrayList<MoveInfo> moves = mMovesList.get(i); count = moves.size(); for (int j = count - 1; j >= 0; j--) { MoveInfo moveInfo = moves.get(j); ViewHolder item = moveInfo.holder; View view = item.itemView; ViewCompat.setTranslationY(view, 0); ViewCompat.setTranslationX(view, 0); dispatchMoveFinished(moveInfo.holder); moves.remove(j); if (moves.isEmpty()) { mMovesList.remove(moves); } } } listCount = mAdditionsList.size(); for (int i = listCount - 1; i >= 0; i--) { ArrayList<ViewHolder> additions = mAdditionsList.get(i); count = additions.size(); for (int j = count - 1; j >= 0; j--) { ViewHolder item = additions.get(j); View view = item.itemView; ViewCompat.setAlpha(view, 1); dispatchAddFinished(item); additions.remove(j); if (additions.isEmpty()) { mAdditionsList.remove(additions); } } } listCount = mChangesList.size(); for (int i = listCount - 1; i >= 0; i--) { ArrayList<ChangeInfo> changes = mChangesList.get(i); count = changes.size(); for (int j = count - 1; j >= 0; j--) { endChangeAnimationIfNecessary(changes.get(j)); if (changes.isEmpty()) { mChangesList.remove(changes); } } } cancelAll(mRemoveAnimations); cancelAll(mMoveAnimations); cancelAll(mAddAnimations); cancelAll(mChangeAnimations); dispatchAnimationsFinished(); } void cancelAll(List<ViewHolder> viewHolders) { for (int i = viewHolders.size() - 1; i >= 0; i--) { ViewCompat.animate(viewHolders.get(i).itemView).cancel(); } } /** * {@inheritDoc} * <p> * If the payload list is not empty, DefaultItemAnimator returns <code>true</code>. * When this is the case: * <ul> * <li>If you override {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)}, both * ViewHolder arguments will be the same instance. * </li> * <li> * If you are not overriding {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)}, * then DefaultItemAnimator will call {@link #animateMove(ViewHolder, int, int, int, int)} and * run a move animation instead. * </li> * </ul> */ @Override public boolean canReuseUpdatedViewHolder(@NonNull ViewHolder viewHolder, @NonNull List<Object> payloads) { return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads); } private static class VpaListenerAdapter implements ViewPropertyAnimatorListener { VpaListenerAdapter() { } @Override public void onAnimationStart(View view) {} @Override public void onAnimationEnd(View view) {} @Override public void onAnimationCancel(View view) {} }}
分割线
import android.support.v7.widget.RecyclerView;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.view.View;/** * Created by wnw on 16-5-22. */public class MyDecoration extends RecyclerView.ItemDecoration { private Context mContext; private Drawable mDivider; private int mOrientation; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; //我们通过获取系统属性中的listDivider来添加,在系统中的AppTheme中设置 public static final int[] ATRRS = new int[]{ android.R.attr.listDivider }; public MyDecoration(Context context, int orientation) { this.mContext = context; final TypedArray ta = context.obtainStyledAttributes(ATRRS); this.mDivider = ta.getDrawable(0); ta.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, RecyclerView.State state) { if (mOrientation == HORIZONTAL_LIST) { drawVerticalLine(c, parent, state); } else { drawHorizontalLine(c, parent, state); } } //画横线, 这里的parent其实是显示在屏幕显示的这部分 public void drawHorizontalLine(Canvas c, RecyclerView parent, RecyclerView.State state) { int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); //获得child的布局信息 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); //Log.d("wnw", left + " " + top + " "+right+" "+bottom+" "+i); } } //画竖线 public void drawVerticalLine(Canvas c, RecyclerView parent, RecyclerView.State state) { int top = parent.getPaddingTop(); int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); //获得child的布局信息 final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int left = child.getRight() + params.rightMargin; final int right = left + mDivider.getIntrinsicWidth(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } //由于Divider也有长宽高,每一个Item需要向下或者向右偏移 @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (mOrientation == HORIZONTAL_LIST) { //画横线,就是往下偏移一个分割线的高度 outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { //画竖线,就是往右偏移一个分割线的宽度 outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } }}
添加styles
<item name="android:listDivider">@drawable/divider</item>
divider.xml
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="#7b7a7a"/> <size android:height="1dp"/></shape>
0 0
- 简单RecyclerView入门
- Android RecyclerView简单入门介绍
- Android RecyclerView简单入门学习
- RecyclerView入门
- RecyclerView入门
- RecyclerView(入门)
- RecyclerView 最佳入门
- RecyclerView的初级入门
- RecyclerView入门简介
- RecyclerView的入门使用
- RecyclerView入门详解
- Android入门之RecyclerView
- RecyclerView简单详解
- RecyclerView的简单使用
- RecyclerView 的简单使用
- recyclerview的简单使用
- Recyclerview的简单使用
- RecyclerView的简单使用
- 2017 年 PHP 程序员未来路在何方?
- Android如何使注解过时的Java文件
- cygwin
- Oracle EBS控制会话时间及超时
- [Android开发从零开始].13.Table_Layout学习
- 简单RecyclerView入门
- chipchunp取碰撞点坐标
- BZOJ1026——windy数(数位DP)
- 自动化工具ansible基本命令和使用方式学习笔记
- linux 在线和离线安装Mplayer视频播放器
- CodeForces 682B Alyona and Mex
- 乱搞——洛谷P1311 选择客栈
- vue.js+ element 增删改查
- service层处理事务