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这是第五篇了,,,,写得好恶心,,,,
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)