您的位置:首页 > 其它

侧滑菜单(一):带缩放动画

2016-12-06 13:31 85 查看


实现效果





实现代码

新建项目A
新建自定义控件Draglayout继承FrameLayout
/**
* Created by Administrator on 2016/9/30.
* 创建自定义控件
*/
public class Draglayout extends FrameLayout {

public Draglayout(Context context) {
this(context,null);
}

public Draglayout(Context context, AttributeSet attrs) {
this(context, attrs,-1);
}

public Draglayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

//初始化控件
init();
}

/**
* 初始化控件
*/
private void init() {

}
}

对activity_main.xml进行修改
<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"
>

<com.one1go.draglayout.Draglayout
android:background="@drawable/bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</com.one1go.draglayout.Draglayout>
</RelativeLayout>

新建一个menu.xml布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#6f599c">

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/head"/>

</LinearLayout>

新建一个main.xml布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#3c3645">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#18b4ed">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="10dp"
android:src="@drawable/head"/>
</LinearLayout>

</LinearLayout>

对activity_main.xml添加以上两个布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
>

<com.itheima.draglayout.Draglayout
...
>
<!--在上面的在下面-->
<include layout="@layout/menu"/>
<include layout="@layout/main"/>
</com.itheima.draglayout.Draglayout>
</RelativeLayout>

在清单文件中去除标题栏:由于MainActivity中继承的是AppCompatActivity,所以它没有title,只有actionbar
application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.NoActionBar">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

实现界面的左右上下滑动:在DrawLayout中进行修改
/**
* Created by Administrator on 2016/x/xx.
* 创建自定义控件
*/
public class Draglayout extends FrameLayout {

private ViewDragHelper helper;
...

public Draglayout(Context context, AttributeSet attrs, int defStyleAttr) {
...
}

/**
* 初始化控件
* Google I/O ViewDragHelper封装了触摸,滑动等操作,可以轻松的控件触摸滑动
*/
private void init() {
//创建ViewDragHelper
//参数1 : 为谁处理触摸操作
helper = ViewDragHelper.create(this,callback);
}

/**
* 新建一个callback
*/
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {

/**
* 尝试捕获视图
* @param child 被捕获的子视图
* @param pointerId 多指触摸,某个手指的id
* @return  如果返回true,表示所有的孩子都可以被触摸,返回true表示可以移动
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}

/**
* 处理水平移动
* @param child 被触摸的孩子
* @param left  oldLeft + dx = newLeft
* @param dx    系统每隔一段时间检测手指移动的距离
* @return
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return left;
}

/**
* 处理垂直移动
* @param child
* @param top
* @param dy
* @return
*/
//        @Override
//        public int clampViewPositionVertical(View child, int top, int dy) {
//            return top;
//        }
};

/**
* 让helper接手触摸事件的处理
* @param event
* @return  必须返回true才能处理
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
helper.processTouchEvent(event);
return true;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return helper.shouldInterceptTouchEvent(ev);
}

}

处理滑动的最大范围:DrawLayout -- 1.在当前控件及其子控件全部测量完的时候,调用此方法。
/*自定义控件的4个基本流程
* 1,加载
* 2,测量
* 3,布局
* 4,绘制
* */
/**
* 在当前控件及其子控件全部加载完毕时,调用此方法
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();

//对当前加入的控件的子视图进行限制
//代码健壮性处理

//孩子的数目不能超过2个
if(getChildCount() != 2) {
throw new RuntimeException("Are you kedding me?there only hava two childs");
}

//必须包含ViewGroup
if(!(getChildAt(0) instanceof ViewGroup) || !(getChildAt(1) instanceof  ViewGroup)) {
throw new RuntimeException("hehe,you never can use it if it isn't ViewGroup");
}

menu = getChildAt(0);
main = getChildAt(1);
}

处理滑动的最大范围:DrawLayout -- 2.获取在onMeasure方法执行后执行,可以获得测量结果

/**
* 在onMeasure()方法执行后执行,可以获得测量结果
* @param w
* @param h
* @param oldw
* @param oldh
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);

int width = main.getMeasuredWidth();
//获取最大拖动范围
maxDragRange = (int) (width * 0.6f);
}

处理滑动的最大范围:DrawLayout -- 处理移动的最大范围

/**
* 新建一个callback
*/
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {

...

...
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//处理滑动的最大范围
if(child == main) {
if(left < 0) {
left = 0;
} else if(left > maxDragRange) {
left = maxDragRange;
}
}
return left;
}
...
};

menu的滑动处理:DragLayout
/**
* Created by Administrator on 2016/9/30.
* 创建自定义控件
*/
public class Draglayout extends FrameLayout {

private ViewDragHelper helper;
private View menu;
private View main;
private int maxDragRange;

...
...
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {

...
/**
* 位置已经便改变的回掉方法
* @param changedView   被改变位置的孩子视图
* @param left  已经移动的left
* @param top
* @param dx    手指移动的dx
* @param dy
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
//判断当前的视图是menu的时候
//1.禁止menu滑动
//2.将meun移动的距离传给main
if(changedView == menu) {
//滑动的底层都是调用这个代码
menu.offsetLeftAndRight(-dx);

//处理滑动menu造成menu移动的边界范围
int oldLeft = main.getLeft();
int newLeft = oldLeft + dx;

//限制newLeft的范围
if(newLeft > maxDragRange) {
newLeft = maxDragRange;
} else if(newLeft < 0) {
newLeft = 0;
}

int newDx = newLeft - oldLeft;
main.offsetLeftAndRight(newDx);

}
}

...
};
...
}

抬起手的操作
public class Draglayout extends FrameLayout {

...
private ViewDragHelper.Callback callback = new ViewDragHelpe
acea
r.Callback() {
...
/**
* 释放视图的回调
* @param releasedChild 被释放的孩子视图
* @param xvel  释放瞬间x方向的速度
* @param yvel
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
//判断当释放视图的时候,main的左边距与最大范围的一半进行比较
if(main.getLeft() < maxDragRange / 2) {
close();
} else {
open();
}
}
...
};

/**
* 开启侧滑菜单
*/
private void open() {
//设置目标点
//平滑的开始滚动视图
if(helper.smoothSlideViewTo(main,maxDragRange,0)) {
//绘制界面
invalidate();
}
}

/**
* 计算滚动过程中的某帧
*/
@Override
public void computeScroll() {
super.computeScroll();
if(helper.continueSettling(true)) {
invalidate();
}
}

/**'
* 关闭侧滑菜单
*/
private void close() {
if(helper.smoothSlideViewTo(main,0,0)) {
//绘制界面
invalidate();
}
}

...
}

让main缩放
...
public class Draglayout extends FrameLayout {

...

/**
* 新建一个callback
*/
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {

...

/**
* 位置已经便改变的会掉方法
* @param changedView   被改变位置的孩子视图
* @param left  已经移动的left
* @param top
* @param dx    手指移动的dx
* @param dy
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
...
if(changedView == menu) {
...
}
//计算移动的距离占总距离的百分比
float percent = main.getLeft() * 1.0f / maxDragRange;
executeAnimation(percent);
}

...
};

/**
* 执行移动时main的缩放动画
* @param percent
*/
private void executeAnimation(float percent) {
//        Log.i("test", "executeAnimation: percent=" + percent);
//1.让main越来越小 : 1.0f - 0.75f
//估值器.插值器
float evaluateResult = evaluate(percent,1.0f,0.75f);
//2.让main缩放
main.setScaleX(evaluateResult);
main.setScaleY(evaluateResult);
}

private float evaluate(float fraction, float startValue, float endValue) {
return startValue + fraction * (endValue - startValue);
}

...
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  侧滑 Studio 动画