如何在android中实现swipe的手势功能及页面拖动动画

如何在android中实现swipe的手势功能及页面拖动动画,第1张

SimpleOnGestureListener. 你只需要实现自己所关心的手势就可以了.

Swipe在android里面是叫Fling ^_^

首先创建自己的一个手势detector类:

private static final int SWIPE_MIN_DISTANCE = 120private static final int SWIPE_MAX_OFF_PATH = 250private static final int SWIPE_THRESHOLD_VELOCITY = 200然后在onFling方法中, 判断是不是一个合理的swipe动作: if(e1.getX() - e2.getX() >SWIPE_MIN_DISTANCE &&Math.abs(velocityX) >SWIPE_THRESHOLD_VELOCITY) { viewFlipper.setInAnimation(slideLeftIn)viewFlipper.setOutAnimation(slideLeftOut)viewFlipper.showNext()} else if (e2.getX() - e1.getX() >SWIPE_MIN_DISTANCE &&Math.abs(velocityX) >SWIPE_THRESHOLD_VELOCITY) { viewFlipper.setInAnimation(slideRightIn)viewFlipper.setOutAnimation(slideRightOut)viewFlipper.showPrevious()}里的viewFlipper是含有多个view的一个container, 可以很方便的调用prev/next view, 加上animation动画, 可以达到一些不错的效果:

viewFlipper = (ViewFlipper)findViewById(R.id.flipper)slideLeftIn = AnimationUtils.loadAnimation(this, R.anim.slide_left_in)slideLeftOut = AnimationUtils.loadAnimation(this, R.anim.slide_left_out)slideRightIn = AnimationUtils.loadAnimation(this, R.anim.slide_right_in)slideRightOut = AnimationUtils.loadAnimation(this, R.anim.slide_right_out)自定义的animation可以查看具体的XML, 比如从左边进来的一个动画:

app自动化测试过程中,经常会遇到滑动屏幕 *** 作,appium框架的话我们可以使用webdriver提供的swipe()方法来对屏幕页面进行上滑、下滑、左滑、右滑 *** 作。

swipe()方法的参数说明:

start_x:起始横坐标

start_y:起始纵坐标

end_x:结束时横坐标

end_y:结束时纵坐标

duration:滑动持续时间,单位毫秒,默认None(一般设置500-1000毫秒比较合适)

调用baseOpera.py模块中的滑动方法,向上滑动查看今日头条首页新闻,简单示意如下:

其实主要靠:paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN))这行代码,为什么呢,我给大家解释下,SRC_IN这种模式,两个绘制的效果叠加后取交集展现后图,怎么说呢,咱们第一个绘制的是个圆形,第二个绘制的是个Bitmap,于是交集为圆形,展现的是BItmap,就实现了圆形图片效果。圆角,其实就是先绘制圆角矩形,是不是很简单,以后别人再说实现圆角,你就把这一行代码给他就行了。

从Android的示例中,给大家证明一下:

下面有一张PorterDuff.Mode的16中效果图,咱们的只是其一:

源码咱们只关心谁先谁后绘制的:

[java] view plaincopy

canvas.translate(x, y)

canvas.drawBitmap(mDstB, 0, 0, paint)

paint.setXfermode(sModes[i])

canvas.drawBitmap(mSrcB, 0, 0, paint)

paint.setXfermode(null)

canvas.restoreToCount(sc)

可以看出先绘制的Dst,再绘制的Src,最后的展示是SrcIn那个图:显示的区域是二者交集,展示的是Src(后者)。和咱们前面结论一致。效果16种,大家可以自由组合展示不同的效果。

好了,原理和核心代码解释完成。下面开始写自定义View。

1、自定义属性:

[html] view plaincopy

<?xml version="1.0" encoding="utf-8"?>

<resources>

<attr name="borderRadius" format="dimension" />

<attr name="type">

<enum name="circle" value="0" />

<enum name="round" value="1" />

</attr>

<attr name="src" format="reference"></attr>

<declare-styleable name="CustomImageView">

<attr name="borderRadius" />

<attr name="type" />

<attr name="src" />

</declare-styleable>

</resources>

2、构造中获取自定义的属性:

[java] view plaincopy

/**

* TYPE_CIRCLE / TYPE_ROUND

*/

private int type

private static final int TYPE_CIRCLE = 0

private static final int TYPE_ROUND = 1

/**

* 图片

*/

private Bitmap mSrc

/**

* 圆角的大小

*/

private int mRadius

/**

* 控件的宽度

*/

private int mWidth

/**

* 控件的高度

*/

private int mHeight

public CustomImageView(Context context, AttributeSet attrs)

{

this(context, attrs, 0)

}

public CustomImageView(Context context)

{

this(context, null)

}

/**

* 初始化一些自定义的参数

*

* @param context

* @param attrs

* @param defStyle

*/

public CustomImageView(Context context, AttributeSet attrs, int defStyle)

{

super(context, attrs, defStyle)

TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomImageView, defStyle, 0)

int n = a.getIndexCount()

for (int i = 0i <ni++)

{

int attr = a.getIndex(i)

switch (attr)

{

case R.styleable.CustomImageView_src:

mSrc = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0))

break

case R.styleable.CustomImageView_type:

type = a.getInt(attr, 0)// 默认为Circle

break

case R.styleable.CustomImageView_borderRadius:

mRadius= a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f,

getResources().getDisplayMetrics()))// 默认为10DP

break

}

}

a.recycle()

}

3、onMeasure中获取控件宽高:

[java] view plaincopy

/**

* 计算控件的高度和宽度

*/

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

{

// super.onMeasure(widthMeasureSpec, heightMeasureSpec)

/**

* 设置宽度

*/

int specMode = MeasureSpec.getMode(widthMeasureSpec)

int specSize = MeasureSpec.getSize(widthMeasureSpec)

if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate

{

mWidth = specSize

} else

{

// 由图片决定的宽

int desireByImg = getPaddingLeft() + getPaddingRight()

+ mSrc.getWidth()

if (specMode == MeasureSpec.AT_MOST)// wrap_content

{

mWidth = Math.min(desireByImg, specSize)

} else

mWidth = desireByImg

}

/***

* 设置高度

*/

specMode = MeasureSpec.getMode(heightMeasureSpec)

specSize = MeasureSpec.getSize(heightMeasureSpec)

if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate

{

mHeight = specSize

} else

{

int desire = getPaddingTop() + getPaddingBottom()

+ mSrc.getHeight()

if (specMode == MeasureSpec.AT_MOST)// wrap_content

{

mHeight = Math.min(desire, specSize)

} else

mHeight = desire

}

setMeasuredDimension(mWidth, mHeight)

}

4、根据Type绘制:

[java] view plaincopy

/**

* 绘制

*/

@Override

protected void onDraw(Canvas canvas)

{

switch (type)

{

// 如果是TYPE_CIRCLE绘制圆形

case TYPE_CIRCLE:

int min = Math.min(mWidth, mHeight)

/**

* 长度如果不一致,按小的值进行压缩

*/

mSrc = Bitmap.createScaledBitmap(mSrc, min, min, false)

canvas.drawBitmap(createCircleImage(mSrc, min), 0, 0, null)

break

case TYPE_ROUND:

canvas.drawBitmap(createRoundConerImage(mSrc), 0, 0, null)

break

}

}

/**

* 根据原图和变长绘制圆形图片

*

* @param source

* @param min

* @return

*/

private Bitmap createCircleImage(Bitmap source, int min)

{

final Paint paint = new Paint()

paint.setAntiAlias(true)

Bitmap target = Bitmap.createBitmap(min, min, Config.ARGB_8888)

/**

* 产生一个同样大小的画布

*/

Canvas canvas = new Canvas(target)

/**

* 首先绘制圆形

*/

canvas.drawCircle(min / 2, min / 2, min / 2, paint)

/**

* 使用SRC_IN,参考上面的说明

*/

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN))

/**

* 绘制图片

*/

canvas.drawBitmap(source, 0, 0, paint)

return target

}

/**

* 根据原图添加圆角

*

* @param source

* @return

*/

private Bitmap createRoundConerImage(Bitmap source)

{

final Paint paint = new Paint()

paint.setAntiAlias(true)

Bitmap target = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888)

Canvas canvas = new Canvas(target)

RectF rect = new RectF(0, 0, source.getWidth(), source.getHeight())

canvas.drawRoundRect(rect, mRadius, mRadius, paint)

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN))

canvas.drawBitmap(source, 0, 0, paint)

return target

}

好了,我就不解析代码了,自定义View这是第五篇了,,,,写得好恶心,,,,


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/7964652.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-12
下一篇 2023-04-12

发表评论

登录后才能评论

评论列表(0条)

保存