已经坚持写blog一段时间了,干什么事都需要恒心,虽然我的博客浏览量很少,但如果我能把自己所学的总结一遍的话,对于自己也是一个不小的收获,所以,骚年,加油吧!
本项目的github地址:项目链接地址
我们今天要实现的叫PullDoorView,有点类似抽屉的感觉,一些splash界面,或者一些特定的场合会用得到,不管用不用得到,我们主要是了解其实现原理就ok了。没有找到什么好的录屏工具,控件随着手的滑动而移动,当手放开的时候,如果滑动超过控件的一般,那么久自动打开,反正自动关闭,先看看效果图:
实现思路:自定义view,通过监听View的滑动事件,然后调用View的scrollto方法移动子view的位置,监听ACTION_UP操作,当滑动的位置大于控件的一半的时候调用scroller的startScroller方法,开始自动移动子view的位置。
好了,咱们直接上代码了
第一步:创建一个View继承ViewGroup,然后覆盖三个构造方法(自定义view的老套路了)
这里我们就直接继承一个FramLayout了
**
* Author:Yqy
* Date:2016-08-03
* Desc:拉伸开门View
* Company:cisetech
*/
public class PullDoorView extends FrameLayout{
public PullDoorView(Context context) {
this(context, null);
}
public PullDoorView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PullDoorView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setUpView();
}
}
第二步:初始化一些操作,创建一个Scroller,在Framlayout底部放一个ImageView,然后放上我们自己的一张图片,放一个TextView在ImageView的上面,并靠父控件的底部,用来提示“上拉消失的提示”
/**
* 初始化View
*/
private void setUpView() {
/**
* 创建一个带BounceInterpolator插值器(结束时候前后跳动)
* 的Scroller
*/
mInterpolator=new BounceInterpolator();
mScroller=new Scroller(getContext(),mInterpolator);
/**
* 创建一个ImageView放置父控件
*/
ImageView imageView=new ImageView(getContext());
FrameLayout.LayoutParams imgLp=new FrameLayout.LayoutParams(-1,-1);
imageView.setImageResource(R.mipmap.ic_introduction);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
addView(imageView, imgLp);
/**
* 创建一个TextView,放置控件底部
*/
FrameLayout.LayoutParams textLp=new FrameLayout.LayoutParams(-2,-2);
textLp.gravity= Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM;
TextView textView=new TextView(getContext());
textView.setText("向上滑动关闭此广告");
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14.5f);
textView.setTextColor(Color.DKGRAY);
textView.setLayoutParams(textLp);
addView(textView);
/**
* 创建一个alpha动画
*/
AlphaAnimation a=new AlphaAnimation(0,1f);
a.setDuration(1000);
a.setRepeatCount(Animation.INFINITE);
a.setRepeatMode(Animation.REVERSE);
textView.startAnimation(a);
}
第三步:根据手指滑动的距离调用View的scrollTo方法,移动子View
private float lastX,lastY;
@Override
public boolean onTouchEvent(MotionEvent event) {
int action=event.getAction();
/**
* 计算距离差
*/
int durationY= (int) (event.getY()-lastY);
switch (action){
case MotionEvent.ACTION_DOWN:
/**
* 记录按下的位置
*/
lastX=event.getX();
lastY=event.getY();
if(!mScroller.isFinished()){
mScroller.abortAnimation();
}
scrollTo(0, 0);//关闭
return true;
case MotionEvent.ACTION_MOVE:
/**
* 只处理向上滑
*/
if(durationY<0){
scrollBy(0, -(int) durationY);
}
lastX=event.getX();
lastY=event.getY();
break;
case MotionEvent.ACTION_UP:
if(getScrollY()>=getHeight()/2){//当滑动到控件一半的时候自动上滑打开控件
mScroller.startScroll(0, getScrollY(),0,getHeight(),500);
}else{//滑动小于一般,自动下滑回到原位
mScroller.startScroll(0, getScrollY(),0,-getScrollY(),500);
}
/**
* 记得去重新绘制一下
*/
invalidate();
break;
}
return super.onTouchEvent(event);
}
第四步:也是最关键的一步,调用Scroller的startScroller自动滑动,然后复写View的computeScroll方法重绘制View
/**
* 当控件不断滑动的时候会回调此方法
*/
@Override
public void computeScroll() {
super.computeScroll();
if(mScroller.computeScrollOffset()){//判断是否在自动滑动中
int currY = mScroller.getCurrY();
scrollTo(0,currY);
invalidate();//一定要记得重新绘制View哦
}
}
case MotionEvent.ACTION_UP:
if(getScrollY()>=getHeight()/2){//当滑动到控件一半的时候自动上滑打开控件
mScroller.startScroll(0, getScrollY(),0,getHeight(),500);
}else{//滑动小于一般,自动下滑回到原位
mScroller.startScroll(0, getScrollY(),0,-getScrollY(),500);
}
/**
* 记得去重新绘制一下
*/
invalidate();
break;
}
第五步:测试一下效果
layout文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.cisetech.customer.pulldoorview.MainActivity">
<com.cisetech.customer.pulldoorview.PullDoorView
android:background="#ffff00"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
总结:
至于Scroller的其他一些用法,大家baidu一下或者是查看一下api文档都有写的,坚持坚持!!!!一定会有收获的。