本文将介绍android–RecyclerView–NotifyItemInsert上没有动画的详细情况,特别是关于androidrecyclerview动态添加item的相关信息。我们将通过案例分析
本文将介绍android – RecyclerView – NotifyItemInsert上没有动画的详细情况,特别是关于android recyclerview动态添加item的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于Android MotionLayout + Recyclerview,recyclerview中的视图不可单击、Android RecyclerView ItemDecoration 类解析、android RecyclerView ItemDecoration 详解、Android RecyclerView 更新子项目 notifyItemChanged的知识。
本文目录一览:- android – RecyclerView – NotifyItemInsert上没有动画(android recyclerview动态添加item)
- Android MotionLayout + Recyclerview,recyclerview中的视图不可单击
- Android RecyclerView ItemDecoration 类解析
- android RecyclerView ItemDecoration 详解
- Android RecyclerView 更新子项目 notifyItemChanged
android – RecyclerView – NotifyItemInsert上没有动画(android recyclerview动态添加item)
RecyclerViewAdapter:
@Override public void onNewDatabaseEntryAdded() { //item added to top of the list notifyItemInserted(0); } public FileViewerAdapter(Context context) { super(); mContext = context; mDatabase = new DBHelper(mContext); mDatabase.setonDatabaseChangedListener(this); }
sqlite数据库:
private static OnDatabaseChangedListener mOnDatabaseChangedListener; public static void setonDatabaseChangedListener(OnDatabaseChangedListener listener) { mOnDatabaseChangedListener = listener; } public long addRecording(String recordingName,String filePath,long length) { sqliteDatabase db = getWritableDatabase(); ContentValues cv = new ContentValues(); cv.put(DBHelperItem.COLUMN_NAME_RECORDING_NAME,recordingName); cv.put(DBHelperItem.COLUMN_NAME_RECORDING_FILE_PATH,filePath); cv.put(DBHelperItem.COLUMN_NAME_RECORDING_LENGTH,length); cv.put(DBHelperItem.COLUMN_NAME_TIME_ADDED,System.currentTimeMillis()); long rowId = db.insert(DBHelperItem.TABLE_NAME,null,cv); if (mOnDatabaseChangedListener != null) { mOnDatabaseChangedListener.onNewDatabaseEntryAdded(); } return rowId; }
监听器:
public interface OnDatabaseChangedListener{ void onNewDatabaseEntryAdded(); void onDatabaseEntryRenamed(); }
编辑:
我应该提一下,如果我使用NotifyDataSetChanged而不是NotifyItemInserted,那么新项目会立即显示,但RecyclerView不会滚动到列表的顶部. (手动必须向上滚动才能看到它).
解决方法
Android MotionLayout + Recyclerview,recyclerview中的视图不可单击
好的,我已经解决了这个错误。该错误来自recyclerview和motionlayot之间的兼容性。只需将您的recyclerview版本设置为最新版本即可。
Android RecyclerView ItemDecoration 类解析
一、前言
<font face = 黑体>毫无疑问,RecyclerView 是 Android 中最重要的系统组件之一,它的出现就是为了高效代替 ListView 和 GridView。
<font face = 黑体>今天,我们来讲讲 RecyclerView 中的静态内部类 ItemDecoration。顾名思义 ItemDecoration 就是 Item 的装饰,我们可以在 Item 的上下左右添加自定义的装饰,从而丰富 Item 的 UI 效果。
二、RecyclerView 基础知识
<font face = 黑体>我们都知道 RecyclerView 里面就是一个又一个的 Item,但是其实这些 Item 外面包裹着一个矩形,只是我们再使用 RecyclerView 的时候 Left、Right、Top 和 Bottom 默认都是 0,所以我们看不到这些矩形,具体如下图所示:
三、DividerItemDecoration(系统提供)
<font face = 黑体>我们都知道,使用 RecyclerView 时 ,我们不能像 ListView 那样通过 setDivider() 的方式来设置分割线,但是系统已经为我们提供了一个 DividerItemDecoration 类来设置分割线,这个类就是继承 RecyclerView.ItemDecoration,我们来看下源码:
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
public static final int VERTICAL = LinearLayout.VERTICAL;
private static final String TAG = "DividerItem";
private static final int[] ATTRS = new int[]{ android.R.attr.listDivider };
... ...
... ...
3.1、RecyclerView 简单使用
<font face = 黑体>不设置分割线,效果如下所示:
3.2、使用 DividerItemDecoration 设置分割线
<font face = 黑体>DividerItemDecoration 的使用非常简单,只需添加下面代码即可:
DividerItemDecoration decoration = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(decoration);
<font face = 黑体>具体效果如下所示:
<font face = 黑体>一般情况下以上 RecyclerView 的基本用法便可以实现绝大多数需求,但是某些场景下却远远不够,特别是需要实现比较复杂的 UI 效果的时候,所以这时候就需要利用 ItemDecoration,接下来我们就学习一下 ItemDecoration 的具体使用。
四、ItemDecoration 源码
<font face = 黑体>首先,我们来看一下 ItemDecoration 的源码,这里的源码已经把注释和三个已经被弃用的方法去掉了,具体如下所示:
public abstract static class ItemDecoration {
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull State state) {
onDraw(c, parent);
}
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull State state) {
onDrawOver(c, parent);
}
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull State state) {
getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(), parent);
}
}
<font face = 黑体>从源码中我们可以看出 ItemDecoration 类中就只有三个方法,分别是 onDraw()、onDrawOver() 和 getItemOffsets(),具体作用如下:
- <font face = 黑体>onDraw(): 在子视图上绘制内容,绘制图层在 Item 以下,所以如果绘制区域与 Item 区域相重叠,会被遮挡;
- <font face = 黑体>onDrawOver():同样是绘制内容,但与onDraw() 的区别是,绘制图层在最上层;
- <font face = 黑体>getItemOffsets():设置ItemView的内嵌偏移长度。
4.1、getItemOffsets()
<font face = 黑体>getItemOffsets() 的作用就是设置 Item 的内嵌偏移长度,从上面我们已经知道,RecyclerView 的 Item 外面是包裹着一个矩形的,这个方法就是用来设置矩形与 Item 之间的间隔的。
<font face = 黑体>具体使用:
public class RectItemDecoration extends RecyclerView.ItemDecoration {
// 参数说明:
// 1. outRect:全为 0 的 Rect(包括着Item)
// 2. view:RecyclerView 中的 视图 Item
// 3. parent:RecyclerView 本身
// 4. state:状态
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
// 4个参数分别对应左(Left)、上(Top)、右(Right)、下(Bottom)
// 上述语句代表:左、右、上和下偏移长度=100px
outRect.set(100, 100, 100,100);
}
}
//用自定义分割线类设置分割线
recyclerView.addItemDecoration(new RectItemDecoration());
<font face = 黑体>效果如下所示:(上下左右都设置了 100px 的偏移量)
4.2、onDraw()
<font face = 黑体>onDraw() 的作用是通过 Canvas 对象绘制内容,需要注意的是 onDraw() 绘制会先于 Item 的绘制,所以如果在 onDraw() 中绘制的内容在 Item 边界内,就会被 Item 遮挡住,所以 onDraw() 一般会和 getItemOffsets() 结合一起使用,即在矩形与 Item 的间隔区域内绘制内容。
<font face = 黑体>实例1:在左侧间隔区域绘制一个空心圆,并在下侧间隔区域绘制一个 20px 的红色分割线。
<font face = 黑体>我们先来看效果:
<font face = 黑体>具体代码如下所示:
public class CircleRectDecoration extends RecyclerView.ItemDecoration {
private Paint colorPaint;
private Paint dividerPaint;
// 初始化
public RectItemDecoration() {
colorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
colorPaint.setColor(Color.BLUE);
colorPaint.setStyle(Paint.Style.STROKE);
colorPaint.setStrokeWidth(5);
dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
dividerPaint.setColor(Color.RED);
dividerPaint.setStyle(Paint.Style.FILL);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(100, 0, 0, 20);
}
@Override
public void onDraw(@NonNull Canvas canvas, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDraw(canvas, parent, state);
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
// 需要遍历每个 Item 进行绘制
for (int i = 0; i < parent.getChildCount(); i++) {
View childView = parent.getChildAt(i);
int leftItemWidth = layoutManager.getLeftDecorationWidth(childView);
int bottomItemHeight = layoutManager.getBottomDecorationHeight(childView);
int left = leftItemWidth / 2;
canvas.drawCircle(left, childView.getTop() + childView.getHeight() / 2, 20, colorPaint);
// getItemOffsets() 中的设置的是 bottom = 20px;所以在 drawRect 时,top 为 childView.getBottom, bottom 为top + bottomDecorationHeight
canvas.drawRect(new Rect(leftItemWidth, childView.getBottom(),
childView.getWidth() + leftItemWidth,
childView.getBottom() + bottomItemHeight), dividerPaint);
}
}
<font face = 黑体>getItemOffsets() 是针对每个 item 都会执行一次,也就是说每个 item 的 outRect 可以设置为不同值,但是 onDraw() 是针对 ItemDecoration 的,不是针对 item 的,只执行一次。所以我们在 onDraw() 中绘制的时候,需要遍历每个 item 进行绘制。
4.2、onDrawOver()
<font face = 黑体>onDrawOver() 的作用与 onDraw() 类似,都是通过 Canvas 对象绘制内容,但与onDraw() 的区别是:onDrawOver() 绘制是后于 onDraw() 的,所以绘制内容是不会被 Item 所遮挡的,反而 Item 会被 onDrawOver() 绘制的内容所遮挡。
<font face = 黑体>实例2:在实例1的基础上,绘制一个角标到 Item 上。
<font face = 黑体>我们先来看效果:
<font face = 黑体>具体代码如下所示:
@Override
public void onDrawOver(@NonNull Canvas canvas, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDrawOver(canvas, parent, state);
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = parent.getChildAt(i);
int index = parent.getChildAdapterPosition(view);
float top = view.getTop();
if (index < 3) {
canvas.drawBitmap(mIcon, 120, top, flagPaint);
}
}
}
五、小结
<font face = 黑体>自定义 ItemDecoration 通常要根据需要,复写它的 3 个方法。
- <font face = 黑体>getItemOffsets 撑开 Item 上、下、左、右四个方向的空间;
- <font face = 黑体>onDraw 在 Item 内容之下绘制图形;
- <font face = 黑体>onDrawOver 在 Item 内容之上绘制图形。
<font face = 黑体>ItemDecoration 的作用远不止以上这么一点,我这里只是简单的介绍了下 ItemDecoration 中三个方法的使用,从而使得 RecyclerView 中的 Item 的 UI 更加丰富。
android RecyclerView ItemDecoration 详解
https://www.cnblogs.com/ldq2016/p/5377605.html
Android RecyclerView 更新子项目 notifyItemChanged
在过去 Android 的 ListView 中,如果 ListView 中某一个或者一批项目发生变化,需要通过 adapter 的 notifyDataSetChanged 更新数据到最新,但是从 ListView 演进到现在的 RecyclerView,数据的更新不需要像 ListView 那样 notifyDataSetChanged,而是要采用 RecyclerView 的 notifyItemChanged,传入一个 pos 位置,通知 RecyclerView 该 pos 位置已经失效,需要重新绘制和 UI 更新。现在给出一个例子,上面一个 Button 按钮,下面一个 RecyclerView:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="随机更新" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
每次点击 Button 按钮,将随机更新某一个位置的时间到最新:
package zhangphil.demo;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Random;
public class MainActivity extends Activity {
private ArrayList data = new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for (int i = 0; i < 5; i++) {
data.add(System.currentTimeMillis());
}
RecyclerView mRecyclerView = findViewById(R.id.recycler_view);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setOrientation(LinearLayout.VERTICAL);
mRecyclerView.setLayoutManager(mLayoutManager);
final RecyclerView.Adapter mAdapter = new MyAdapter();
mRecyclerView.setAdapter(mAdapter);
final Random random = new Random();
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = random.nextInt(data.size());
data.set(pos, System.currentTimeMillis());
mAdapter.notifyItemChanged(pos);
Toast.makeText(getApplicationContext(), "更新:" + pos + "," + data.get(pos), Toast.LENGTH_LONG).show();
}
});
}
private class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
public MyAdapter() {
super();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(getApplicationContext()).inflate(android.R.layout.simple_list_item_2, null);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
viewHolder.text1.setText(i + "");
viewHolder.text2.setText(data.get(i) + "");
}
@Override
public int getItemCount() {
return data.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView text1;
public TextView text2;
public ViewHolder(View itemView) {
super(itemView);
text1 = itemView.findViewById(android.R.id.text1);
text1.setTextColor(Color.RED);
text2 = itemView.findViewById(android.R.id.text2);
text2.setTextColor(Color.BLUE);
}
}
}
}
事实上 RecyclerView 的 notifyItemChanged 的底层调用的是 notifyItemRangeChanged:
/**
* Notify any registered observers that the item at <code>position</code> has changed.
* Equivalent to calling <code>notifyItemChanged(position, null);</code>.
*
* <p>This is an item change event, not a structural change event. It indicates that any
* reflection of the data at <code>position</code> is out of date and should be updated.
* The item at <code>position</code> retains the same identity.</p>
*
* @param position Position of the item that has changed
*
* @see #notifyItemRangeChanged(int, int)
*/
public final void notifyItemChanged(int position) {
mObservable.notifyItemRangeChanged(position, 1);
}
该方法使得 RecyclerView 批量范围内(range)数据更新,notifyItemChanged 巧妙的将第二个参数计数器设置为 1 得以实现。后续再介绍 RecyclerView 的 notifyItemRangeChanged。
关于android – RecyclerView – NotifyItemInsert上没有动画和android recyclerview动态添加item的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于Android MotionLayout + Recyclerview,recyclerview中的视图不可单击、Android RecyclerView ItemDecoration 类解析、android RecyclerView ItemDecoration 详解、Android RecyclerView 更新子项目 notifyItemChanged等相关内容,可以在本站寻找。
本文标签: