博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[置顶] android 自定义ListView实现动画特效
阅读量:6379 次
发布时间:2019-06-23

本文共 8938 字,大约阅读时间需要 29 分钟。

通过自定义ListView实现动画特效,被点击元素A向前移,A之前元素往后移动.

重点在于动画的实现:

具体代码如下:

 

package com.open.widget;import java.util.ArrayList;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PaintFlagsDrawFilter;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.Rect;import android.os.Handler;import android.util.AttributeSet;import android.util.Log;import android.view.GestureDetector;import android.view.GestureDetector.SimpleOnGestureListener;import android.view.MotionEvent;import android.view.View;/** *  * @author yanglonghui * */public class HorImageListView extends View {	private int current_OffsetX=0;//当前屏X轴的偏移量	private int cuurent_OffsetY=0;//当前屏Y轴的偏移量	private int moving_OffsetX=0;//当前S手势X轴偏移量	private int moving_OffsetY=0;//当前S手势Y轴偏移量	private int current_Page=1;//当前页码,开始页码为1	private int portraitNumberPerScreen;//每屏头像个数	private int charHeight=0;//一个字的高度	private int maxPage=1;//最大页码		private int current_foucsIndex=0;//当前焦点	private int current_longPressIndex=-1;//当前长按焦点	private int current_clickIndex=0;//当前点击		private int headWidth=0;//头像宽度	private int paddingLeft;//左边距	private Bitmap []bitmapArray;//头像数组	private Rect headRectArray[]=null;//头像位置	private Rect drawingRect=new Rect();    private Bitmap mCircleBitmap=null;    private PorterDuffXfermode xfermode=new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY);    private PaintFlagsDrawFilter pdf=new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);	private Paint paint = new Paint();    {	    paint.setStyle(Paint.Style.STROKE);	    paint.setFlags(Paint.ANTI_ALIAS_FLAG);	    paint.setAntiAlias(true);// 设置画笔的锯齿效果。 true是去除,大家一看效果就明白了     }        private static final int LAYER_FLAGS = Canvas.MATRIX_SAVE_FLAG |            Canvas.CLIP_SAVE_FLAG |            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |            Canvas.FULL_COLOR_LAYER_SAVE_FLAG |            Canvas.CLIP_TO_LAYER_SAVE_FLAG;        private IHeadClick headClickListener;        private Handler mHandler=new Handler();    private ArrayList
headList=new ArrayList
(); public HorImageListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public HorImageListView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public HorImageListView(Context context) { super(context); init(); } private void init() { try { if(android.os.Build.VERSION.SDK_INT>=11) { setLayerType(LAYER_TYPE_SOFTWARE, null); } } catch (Exception e) { e.printStackTrace(); } mGestureDetector=new GestureDetector(new CusGestureListener()); setLongClickable(true); setOnTouchListener(onTouchListener); } public void setAdapter(ArrayList
headList) { this.headList=headList; current_Page=1; current_OffsetX=0; current_clickIndex=0; current_foucsIndex=0; current_longPressIndex=-1; if(headWidth==0) { headWidth=DensityUtil.dip2px(getContext(), 60); } mCircleBitmap=WindowMgr.getInstance().getCircleBitmap(headWidth, headWidth); bitmapArray=WindowMgr.getInstance().getAllBitmaps(headList); headRectArray=new Rect[bitmapArray.length]; for(int i=0;i
portraitNumberPerScreen) { maxPage=(bitmapArray.length%portraitNumberPerScreen==0)?bitmapArray.length/portraitNumberPerScreen:this.bitmapArray.length/portraitNumberPerScreen+1; } else { maxPage=1; } int left = 0; int top = DensityUtil.dip2px(getContext(), 10); int right = 0; int bottom = top+headWidth; for(int i=0;i
0) { canvas.setDrawFilter(pdf); for(int i=0;i
current_clickIndex)//还需要优化 { if(current_Page==1) { drawingRect.left=headRectArray[i].left+current_OffsetX; drawingRect.top=headRectArray[i].top+cuurent_OffsetY; drawingRect.right=headRectArray[i].right+current_OffsetX; drawingRect.bottom=headRectArray[i].bottom+cuurent_OffsetY; } else if(current_Page>1) { } } if(drawingRect.right
getRight()) { break; } if(current_clickIndex!=i) { //绘制头像 canvas.drawBitmap(mCircleBitmap, null, drawingRect, paint); paint.setXfermode(xfermode); canvas.drawBitmap(bitmapArray[i], null, drawingRect, paint); paint.setXfermode(null); } } drawingRect.left=headRectArray[0].left+clickOffsetforwarDx; drawingRect.top=headRectArray[0].top; drawingRect.right=headRectArray[0].right+clickOffsetforwarDx; drawingRect.bottom=headRectArray[0].bottom; int sc = canvas.saveLayer(drawingRect.left, drawingRect.top, drawingRect.right, drawingRect.bottom, null,LAYER_FLAGS); //绘制头像 canvas.drawBitmap(mCircleBitmap, null, drawingRect, paint); paint.setXfermode(xfermode); canvas.drawBitmap(bitmapArray[current_clickIndex], null, drawingRect, paint); paint.setXfermode(null); canvas.restoreToCount(sc); } else { canvas.setDrawFilter(pdf); for(int i=0;i
getRight()) { break; } if(current_longPressIndex==i) { int insetDx=(int)((float)drawingRect.height()/(float)8); drawingRect.inset(insetDx, insetDx); } //绘制头像 canvas.drawBitmap(mCircleBitmap, null, drawingRect, paint); paint.setXfermode(xfermode); canvas.drawBitmap(bitmapArray[i], null, drawingRect, paint); paint.setXfermode(null); } } } } private OnTouchListener onTouchListener=new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { boolean isConsumed =mGestureDetector.onTouchEvent(event); if (isConsumed) return true; if(event.getAction()==MotionEvent.ACTION_CANCEL||event.getAction()==MotionEvent.ACTION_UP) { //----分页代码 int direct=0;//往左边为1,右边为-1,保持不变为0 if(moving_OffsetX>getMeasuredWidth()/2)//向右边滑过半屏 { current_Page--; direct=1; if(current_Page<1) { current_Page=1; direct=0; } } else if(moving_OffsetX<-getMeasuredWidth()/2)//向左边滑过半屏 { current_Page++; direct=-1; if(current_Page>maxPage) { current_Page=maxPage; direct=0; } } int old=current_OffsetX+moving_OffsetX; int newX=current_OffsetX+direct*getMeasuredWidth(); if(direct!=0) { current_foucsIndex=(current_Page-1)*portraitNumberPerScreen; if(null!=headClickListener) headClickListener.onItemClick(current_foucsIndex); } Log.v("dx:"+current_OffsetX, "----------------------"); if(current_longPressIndex!=-1) { invalidate(); current_longPressIndex=-1;//恢复 return false; } else { mHandler.post(new SmoothRunnable(old, newX)); } return false; } invalidate(); return isConsumed; } }; private GestureDetector mGestureDetector; private class CusGestureListener extends SimpleOnGestureListener { private Rect mDragRect=new Rect(); @Override public boolean onSingleTapUp(MotionEvent e) { Log.v("CusGestureListener", "onSingleTapUp"); int x=(int) e.getX(); int y=(int) e.getY(); boolean isInner=false; Rect mRect=new Rect(); for(int i=0;i
=y) { isInner=true; } else { break; } } if(mRect.contains(x, y)) { current_foucsIndex=i; current_clickIndex=i; //动画:被点击向前移动,未点击向后移动 if(null!=mClickRunnable) { mClickRunnable.stop(); } mClickRunnable=new ClickRunnable(current_clickIndex); mHandler.post(mClickRunnable); } } return super.onSingleTapUp(e); } @Override public void onLongPress(MotionEvent e) {// Log.v("CusGestureListener", "onLongPress"); int x=(int) e.getRawX(); int y=(int) (e.getRawY()-WindowMgr.getInstance().getStatusBarHeight(getContext())); Rect mRect=new Rect(); for(int i=0;i
0) { current_Page--; direct=1; if(current_Page<1) { current_Page=1; direct=0; } } else { current_Page++; direct=-1; if(current_Page>maxPage) { current_Page=maxPage; direct=0; } } int old=current_OffsetX+moving_OffsetX; int newX=current_OffsetX+direct*getMeasuredWidth(); mHandler.post(new SmoothRunnable(old, newX)); return true; } @Override public void onShowPress(MotionEvent e) {// Log.v("CusGestureListener", "onShowPress"); super.onShowPress(e); } @Override public boolean onDown(MotionEvent e) {// Log.v("CusGestureListener", "onDown"); moving_OffsetX=0; mDragRect.set(getLeft(), getTop(), getRight(), getBottom()); return super.onDown(e); } @Override public boolean onDoubleTap(MotionEvent e) {// Log.v("CusGestureListener", "onDoubleTap"); return super.onDoubleTap(e); } @Override public boolean onDoubleTapEvent(MotionEvent e) {// Log.v("CusGestureListener", "onDoubleTapEvent"); return super.onDoubleTapEvent(e); } @Override public boolean onSingleTapConfirmed(MotionEvent e) {// Log.v("CusGestureListener", "onSingleTapConfirmed"); return super.onSingleTapConfirmed(e); } } //平滑移动 private class SmoothRunnable implements Runnable { private int startDx; private int endDx; private long duration=250; private long interval=10; private long startTime; private long endTime; public SmoothRunnable(int startDx, int endDx) { super(); this.startDx = startDx; this.endDx = endDx; } @Override public void run() { if(startTime==0) { moving_OffsetX=0; startTime=System.currentTimeMillis(); endTime=startTime+duration; } long currentTime=System.currentTimeMillis(); if(currentTime

 

具体的动画效果如下(效果图是丑了点,有录制gif图片软件请推荐一下吧):

Demo下载地址:

你可能感兴趣的文章
TCP连接中time_wait在开发中的影响-搜人以鱼不如授之以渔
查看>>
Oracle数据库机出新帮助不同规模企业迈向云端
查看>>
前端通信:ajax设计方案(六)--- 全局配置、请求格式拓展和优化、请求二进制类型、浏览器错误搜集以及npm打包发布...
查看>>
微服务分布式企业框架 Springmvc+mybatis+shiro+Dubbo+ZooKeeper+Redis+KafKa
查看>>
被《时代周刊》选为年度最佳发明,PS VR靠的竟然是价格
查看>>
通用唯一标识码UUID的介绍及使用。
查看>>
spring笔记--依赖注入之针对不同类型变量的几种注入方式
查看>>
Ajax的简单学习
查看>>
为npm配置taobao源
查看>>
管理邮件用户
查看>>
导出DC数据以便以介质方式安装另一台域控制器
查看>>
Hibernate学习(八):检索方式
查看>>
基于WorsPress+Xampp搭建博客
查看>>
javascript的一些基本概念
查看>>
关于Tomcat上请求的编解码问题
查看>>
WPF“动画序列”框架的初步研究与实现(附源码)
查看>>
Windows Server 2008 多元密码策略配置
查看>>
.NET中的泛型和Java泛型中的类型擦除
查看>>
白利用的集大成者:新型远控木马上演移形换影大法
查看>>
2017必备的八款最佳反勒索软件工具
查看>>