自定义view实现侧滑删除效果
来源:互联网 发布:linux下部署jira 编辑:程序博客网 时间:2024/05/21 06:51
分享一个最近花了点时间才做出来的效果,先看一下做出来的效果,等以后我学会录制视频了,再传动画效果吧
我最开始拿到任务的时候,第一想法是百度,然而很难找到同类的效果,基本都是滑动的时候整个item要跟着一起滑动,最后终于在鸿神的博客里面找到一个在item上弹出一个删除按钮的效果,还顺便解除了listview上下滑动和左右滑动的冲突,在这里方式博客地址以示尊重
http://blog.csdn.net/lmj623565791/article/details/22961279
这里我用的自定义listview,在自定义的listview中放上自定义的view,用ondraw的方式去画三种不同状态的按钮,最开始是想图简单,直接用的两张图片去做切换的效果,后来发现图片会有拉伸的问题,处理起来也比较麻烦,所以直接在大牛的指引下开启了自定义view的道路。
下来我们来看看实现的过程,只需要看自定义listview和view就行啦
HistoryListview.java
package com.example.yj;import android.content.Context;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;import android.widget.ListView;import com.example.yj.R;public class HistoryListview extends ListView { private boolean IsSliding; //是否左右滑动 private HistoryDeleteButtonView mDeleteButton; private LayoutInflater myInflater; private View mCurrentView; //当前手指触摸的View private int mCurrentViewPos; //当前手指触摸的位置 private int xDown;//手指按下时的x坐标 private int yDown; //手指按下时的y坐标 private int xMove;//手指移动时的x坐标 private int yMove; //手指移动时的y坐标 private int touchSlop; //用户滑动的最小距离 public HistoryListview(Context context, AttributeSet attrs) { super(context, attrs); myInflater = LayoutInflater.from(context); touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();//移动的最小距离 View view = myInflater.inflate(R.layout.history_list_item, null); mDeleteButton = (HistoryDeleteButtonView) view.findViewById(R.id.deleteRecord); mDeleteButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //根据当前显示的图片是续播还是删除来处理不同的操作,这里还没到实现功能的时候,就先不出来啦 if(mDeleteButton.getmRedBitmapWidth() == 0){ //续播操作 }else{ //删除操作 } } }); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { int action = ev.getAction(); int x = (int) ev.getX(); int y = (int) ev.getY(); switch (action) { case MotionEvent.ACTION_DOWN: xDown = x; yDown = y; //按下屏幕的时候改变删除按钮的显示状态 if (mDeleteButton.getmRedBitmapWidth()>0) { mDeleteButton.setmRedBitmapWidth(0); mDeleteButton.postInvalidate(); return false; } // 获得当前手指按下时的item的位置 mCurrentViewPos = pointToPosition(xDown, yDown); // 获得当前手指按下时的item View view = getChildAt(mCurrentViewPos - getFirstVisiblePosition()); mCurrentView = view; break; case MotionEvent.ACTION_MOVE: xMove = x; yMove = y; int dx = xMove - xDown; int dy = yMove - yDown; //判断是否是从右到左的滑动 if (xMove < xDown && Math.abs(dx) > touchSlop && Math.abs(dy) < touchSlop) { IsSliding = true; } break; } return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); //从左到右滑动才显示删除按钮 if (IsSliding) { switch (action) { case MotionEvent.ACTION_MOVE: xMove = (int) ev.getX(); int[] location = new int[2]; // 获得当前item的位置x与y mCurrentView.getLocationOnScreen(location); mDeleteButton = (HistoryDeleteButtonView) mCurrentView.findViewById(R.id.deleteRecord); int moveWid = (xDown - xMove) / 2; if (moveWid < 0) { return false; } if (moveWid <= mDeleteButton.getmViewWidth()) { mDeleteButton.setmRedBitmapWidth(moveWid); mDeleteButton.postInvalidate(); } else { moveWid = mDeleteButton.getmViewWidth(); mDeleteButton.setmRedBitmapWidth(moveWid); mDeleteButton.postInvalidate(); } break; case MotionEvent.ACTION_UP: xMove = (int) ev.getX(); moveWid = (xDown - xMove) / 2; //item上滑动两个像素,button上改变一个像素 if (moveWid< mDeleteButton.getmViewWidth()) { mDeleteButton.setmRedBitmapWidth(0); mDeleteButton.postInvalidate(); } IsSliding = false; } return true; } return super.onTouchEvent(ev); }}
这里比较重要的就是要解决侧滑冲突就必须要重写listview的dispatchTouchEvent方法,当左右滑动的距离大于上下滑动的距离时才把事件交给onTouchEvent去处理,然后在dispatchTouchEvent的down事件里面去切换删除按钮和续播按钮的显示,这样才不会出现,滑动完一个,再去滑下一个,然后两个按钮跟着一起动的奇怪场景了
然后在onTouchEvent中的move事件里面去获取当前手指侧滑的距离,再传给我们的自定义view,告诉自定义view当前红色背景需要绘制的宽度
然后是比较重要的画button的地方啦,这个自定义控件我是直接放在history_list_item里面的,但是我在adapter里面并没有对他进行任何操作。
HistoryDeleteButtonView.java
package com.example.yj;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.RectF;import android.util.AttributeSet;import android.view.View;import com.example.yj.R;public class HistoryDeleteButtonView extends View { private static int TEXT_SIZE = 36;//文字大小 private static int BORDER_WIDTH = 2;//边框线宽度 private static int REDUIS = 12;//圆角半径 private static String TEXT = "删除"; private static String RESUME_PALY ="续播"; private Paint mPaint; private RectF mViewRect;//控件显示的矩形区域 //控件的宽高 private int mViewHeight; private int mViewWidth; private int mRedBitmapWidth;//红色背景区域的宽度 private Bitmap redBackgroundBitmap; private Bitmap whiteBackgroundBitmap; private Bitmap resumepalyBitmap; public HistoryDeleteButtonView(Context context, AttributeSet attrs) { super(context, attrs); //初始化画笔 mPaint = new Paint(); mPaint.setTextAlign(Paint.Align.CENTER); mPaint.setTextSize(TEXT_SIZE); mPaint.setAntiAlias(true); } @Override protected void onDraw(Canvas canvas) { //获取红色背景的宽度 mRedBitmapWidth = getmRedBitmapWidth(); if (mRedBitmapWidth == 0) { canvas.drawBitmap(resumepalyBitmap, 0, 0, null); } else if (mRedBitmapWidth < mViewWidth) { //清空一下画布内容,避免重叠 canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); invalidate(); canvas.drawBitmap(whiteBackgroundBitmap, 0, 0, null); canvas.clipRect(mViewWidth-mRedBitmapWidth,0,mViewWidth,mViewHeight); canvas.drawBitmap(redBackgroundBitmap, 0, 0, null); } else { canvas.drawBitmap(redBackgroundBitmap, 0, 0, null); } } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (changed) { mViewHeight = getHeight(); mViewWidth = getWidth(); setmViewWidth(mViewWidth); initBitmaps(); } } //创建三种不同状态下的bitmap(续播,删除) private void initBitmaps() { //设置矩形区域大小(减去了边框的宽度) mViewRect = new RectF(BORDER_WIDTH, BORDER_WIDTH, mViewWidth - BORDER_WIDTH, mViewHeight - BORDER_WIDTH); Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt(); //让文字垂直居中的参数 float baseline = (mViewRect.bottom + mViewRect.top - fontMetrics.bottom - fontMetrics.top) / 2; //创建两个bitmap whiteBackgroundBitmap = Bitmap.createBitmap(mViewWidth, mViewHeight, Bitmap.Config.ARGB_8888); redBackgroundBitmap = Bitmap.createBitmap(mViewWidth, mViewHeight, Bitmap.Config.ARGB_8888); resumepalyBitmap = Bitmap.createBitmap(mViewWidth, mViewHeight, Bitmap.Config.ARGB_8888); Canvas whiteCanvas = new Canvas(whiteBackgroundBitmap); Canvas redCanvas = new Canvas(redBackgroundBitmap); Canvas resumeplayCanvas = new Canvas(resumepalyBitmap); //给画布设置好背景颜色 whiteCanvas.drawColor(getResources().getColor(R.color.history_delete_white)); redCanvas.drawColor(getResources().getColor(R.color.history_delete_white)); resumeplayCanvas.drawColor(getResources().getColor(R.color.history_delete_white)); //用空心线画红色边框 mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(BORDER_WIDTH); mPaint.setColor(getResources().getColor(R.color.history_delete_red)); whiteCanvas.drawRoundRect(mViewRect, REDUIS, REDUIS, mPaint); redCanvas.drawRoundRect(mViewRect, REDUIS, REDUIS, mPaint); resumeplayCanvas.drawRoundRect(mViewRect, REDUIS, REDUIS, mPaint); //用实心线画红色文字和红色背景 mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(getResources().getColor(R.color.history_delete_red)); whiteCanvas.drawText(TEXT, mViewRect.centerX(), baseline, mPaint); redCanvas.drawRoundRect(mViewRect, REDUIS, REDUIS, mPaint); resumeplayCanvas.drawText(RESUME_PALY, mViewRect.centerX(), baseline, mPaint); //用实心线画白色文字 mPaint.setColor(getResources().getColor(R.color.history_delete_white)); redCanvas.drawText(TEXT, mViewRect.centerX(), baseline, mPaint); } public int getmRedBitmapWidth() { return mRedBitmapWidth; } public void setmRedBitmapWidth(int mRedBitmapWidth) { this.mRedBitmapWidth = mRedBitmapWidth; } public int getmViewWidth() { return mViewWidth; } public void setmViewWidth(int mViewWidth) { this.mViewWidth = mViewWidth; }}
我是先采取在在onlayout里面获取到控件宽高的同时去创建好三张不同状态的bitmap,然后再在ondraw里面根据在listview中获取的滑动距离去选择画哪个bitmap
最麻烦的就是需要白色背景和红色背景切换的时候,最开始是先去把bitmap截取好,然后在用canvas把两张bitmap合并起来,大牛只看了一眼就说这样不好,然后就换成clipRect了,然后我就去学了它的用法,最后总算是优化了一点点。
就是这两个啦 ,画图的过程自己觉得还是处理的比较繁琐的,如果有优化的办法,希望我们可以交流一下。
- 自定义view实现侧滑删除效果
- android自定义View之自定义侧滑删除效果
- 自定义view系列(5)--99.99%实现QQ侧滑删除效果
- 自定义view系列(5)--99.99%实现QQ侧滑删除效果
- 自定义view系列(5)--99.99%实现QQ侧滑删除效果
- 自定义view实现侧滑删除功能
- Android 自定义View 实现QQ红点拖动删除效果
- 自定义View(仿QQ侧滑删除实现,ViewDragHelper)
- 自定义View实现刮刮卡效果
- 自定义View实现SwichButton效果
- 自定义 View 实现钟表效果
- 自定义View实现索引效果
- 自定义view实现炸弹效果
- android 自定义view之侧滑效果
- 利用自定义View结合onTouchListener实现QQ侧滑菜单效果
- 自定义View实现转盘旋转效果
- 自定义view实现图文环绕的效果
- 自定义view实现水波荡漾的效果
- ActiveMQ入门实例
- 二叉树------从文件中读取进行层次遍历(顺序表)
- 帮你深入理解OAuth2.0协议
- apk上线之后,终端用户出现的bug的反馈
- 如何给Core Data添加UNIQUENESS约束
- 自定义view实现侧滑删除效果
- nginx怎么限制客户端访问频次与访问次数
- jQuery时间验证和转换为标准格式的时间
- 隐藏滚动条
- NGUI与UGUI制作Loading条
- 算法收藏(stl 背包 并查集 矩阵乘法 java大数)
- innerHTML
- 又学一招——简单的写入文件帮助类
- 机器学习、深度学习教程和代码资源帖