在最新的IOS7中,苹果更改了解锁方式,整个屏幕向右滑动都可以解锁,不再局限在一个小的矩形中。这种文字加亮移动的效果还是继承了下来。之前滑动最左边的滑块,中间文字会有渐变效果,这次文字会跟随着左边的小图标随着用户向左滑动。
滑动触发事件在苹果大致用在了3个地方,1.滑动解锁,2.滑动关机,3.手机处于锁住状态来电,滑动接听。我们来看下Android下的高仿实现。
1. 文字加亮移动效果(这个可能是最吸引眼球的地方)
2. 滑动一段距离,不够触发事件距离的时候就会弹回原来的地方
3. 超过解锁距离,触发事件(解锁 || 关机 || 接听电话)
4.用户已较大加速度滑动,虽然没有超过解锁距离,但是也会解锁,并且会有向右滑动惯性
5.用户按下去,文字变白,动画停止(滑动关机里的效果)
第一感觉的做法是:底下是文字,文字上面有一张图片快速滑动。而且感觉这个动画很熟悉,好像在哪里看过?没错,在原生的Android系统中,开机动画就是这样的效果!
在Android 源码的 \frameworks\base\core\res\assets\images 目录下发现了两张图片,验证了我的想法:
但是这次我没有用这样的方法,:( 。有兴趣的朋友可以试着做下,感觉不难。
LinearGradient是个什么东西呢?可以给定几个颜色,实现下面的效果。如果我们只有两种颜色,灰色和白色,边上两端都是灰色,中间白色,然后使用Android中的ValueAnimator改变位置也可以实现我们要的效果。这样有两个好处:1.逻辑比较单一,只有文字。2.颜色比图片容易更改。
大家可以参考官方API: http://developer.android.com/reference/android/graphics/LinearGradient.html
Create a shader that draws a linear gradient along a line.
Parameters
x0 | The x-coordinate for the start of the gradient line |
---|---|
y0 | The y-coordinate for the start of the gradient line |
x1 | The x-coordinate for the end of the gradient line |
y1 | The y-coordinate for the end of the gradient line |
colors | The colors to be distributed along the gradient line |
positions | May be null. The relative positions [0..1] of each corresponding color in the colors array. If this is null, the the colors are distributed evenly along the gradient line. |
tile | The Shader tiling mode |
跟画线段一样,一个起点,一个终点,中间是颜色。主要讲下最后一个tile的东西,像3.2中的图片那样的效果需要定义为Shader.TileMode.REPEAT,重复的意思。我们这里的需求是不一样的,我们两端需要补充,所以使用Shader.TileMode.CLAMP。
demo:
LinearGradient linearGradient = new LinearGradient(0, 0, 100, 100, new int[] {
Color.RED, Color.GREEN, Color.BLUE, Color.WHITE }, null,
Shader.TileMode.REPEAT);
Paint paint = new Paint();
paint.setShader(linearGradient);
顾名思义可以在一定时间内更改Value。下面是一个小小Demo(在1秒内,值从0到1不断变化):
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.i("update", ((Float) animation.getAnimatedValue()).toString());
}
});
animation.setRepeatCount(Animation.INFINITE);//repeat animation
animation.start();
注意我们还加上了重复次数,定义为无限,这样就是我们想要的效果。
可以参考这篇文章《Android 高仿三星日历》
这里使用了ObjectAnimator中的下面的方法
public static ObjectAnimatorofFloat(Object target, String propertyName, float... values)
target | 要进行动画的控件 |
---|---|
propertyName | 要更改的属性名称,一般控件里SetXX后面的值,比如一个控件可以SetRotation,那么Rotation就是一个属性名称 |
values | 属性更改的两个值,从开始到结束 |
Demo:
// left move animation
ObjectAnimator animLeftMove = ObjectAnimator.ofFloat(mLinearLayout,
"x", mLinearLayout.getX(), -54).setDuration(
1000);
animLeftMove.start();
具体可以参考Android API: http://developer.android.com/reference/android/view/VelocityTracker.html
主要 要知道Android中有这么个东西,用途很广的,比如PageView两页之间快速滑动,ListView快速等。它可以得到x轴和y轴上的加速度,我们这里只需要用到x轴上的。
demo:
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
velocityTracker.computeCurrentVelocity(1000);//should compute first
int velocityX = (int) velocityTracker.getXVelocity();//get volocity in x
if(velocityX > mMinVelocityXToUnlock){
//unlock Success;
return true;
}
return true;
}
核心用的技术讲完了,扯下Android中的自定义控件。我们写的这个如果要复用的话,最好的方式就是封装成一个控件。把文字,解锁难度等成为控件属性,这样就方便了。
public class GradientView extends View {
private int mTextSize;
int mDefaultColor;
int mSlideColor;
private int mWidth,mHeight;
private String mStringToShow;
private Paint mTextPaint;
private float mTextHeight;
public GradientView(Context context) {
super(context);
}
public GradientView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GradientView);
mStringToShow = a.getString(R.styleable.GradientView_StringToShow) ;
mTextSize = (int)a.getDimension(R.styleable.GradientView_TextSize, 40);
mDefaultColor = a.getColor(R.styleable.GradientView_TextColor, Color.GRAY);
mSlideColor = a.getColor(R.styleable.GradientView_SlideColor, Color.WHITE);
a.recycle();
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setColor(mSlideColor);
mTextPaint.setTextSize(mTextSize);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextHeight = mTextPaint.ascent();
}
@Override
protected void onDraw(Canvas canvas) {
//draw something
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mHeight = MeasureSpec.getSize(heightMeasureSpec);
}
}
http://www.waitingfy.com/?attachment_id=808
http://www.waitingfy.com/?p=802