说说实现流程:
(1)为了适配效果更好一点,使用一下代码获取屏幕宽度
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
(2)设置Menu区域滑动之后距离屏幕右边的padding值
//将dp转化成px
mMenuRightPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics());
(3)重写onMeasure,设置menu和content的宽度
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!once) {
mWapper = (LinearLayout) getChildAt(0);
mMenu = (ViewGroup) mWapper.getChildAt(0);
mContent = (ViewGroup) mWapper.getChildAt(1);
//显示设置子View的宽度
mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth - mMenuRightPadding;
mContent.getLayoutParams().width = mScreenWidth;
once = true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
(4)重写onLayout,使得初始状态时,menu隐藏
/**
* 通过设置偏移量将menu隐藏
* @param changed
* @param l
* @param t
* @param r
* @param b
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (changed) {
this.scrollTo(mMenuWidth, 0);
}
}
(5)重写onTouchEvent,监听滑动距离,判定是打开menu还是关闭
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
int scrollX = getScrollX();
if (scrollX >= mMenuWidth/2) {
smoothScrollTo(mMenuWidth, 0);
}else if (scrollX < mMenuWidth) {
smoothScrollTo(0, 0);
}
return true;
}
return super.onTouchEvent(ev);
}
(6)重写onScrollChanged,监听滑动状态并加上各动画
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
float scale = 1.0f * l / mMenuWidth; // 1~0,获取一个渐变scale,用于绘制各动画状态
float scaleContent = 1f - (1 - scale) * 0.3f;// 1~0.7
ObjectAnimator.ofFloat(mMenu, "translationX", mMenuWidth*scale*0.7f).setDuration(0).start();
mContent.setPivotX(0);
mContent.setPivotY(mContent.getHeight() / 2);
ObjectAnimator.ofFloat(mContent, "scaleX", scaleContent).setDuration(0).start();
ObjectAnimator.ofFloat(mContent, "scaleY", scaleContent).setDuration(0).start();
mMenu.setPivotX(0);
mMenu.setPivotY(mMenu.getHeight() / 2);
ObjectAnimator.ofFloat(mMenu, "scaleX", 1.7f-scaleContent).setDuration(0).start();
ObjectAnimator.ofFloat(mMenu, "scaleY", 1.7f-scaleContent).setDuration(0).start();
}
源码:
package com.example.admin.myapplication.custom;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
public class MyHorizontalScrollView extends HorizontalScrollView {
private LinearLayout mWapper;
private ViewGroup mMenu;
private ViewGroup mContent;
private int mScreenWidth; //屏幕宽度
private int mMenuWidth;
//dp
private int mMenuRightPadding = 50;
private boolean once = false;
public MyHorizontalScrollView(Context context) {
this(context, null);
}
public MyHorizontalScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
//将dp转化成px
mMenuRightPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!once) {
mWapper = (LinearLayout) getChildAt(0);
mMenu = (ViewGroup) mWapper.getChildAt(0);
mContent = (ViewGroup) mWapper.getChildAt(1);
//显示设置子View的宽度
mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth - mMenuRightPadding;
mContent.getLayoutParams().width = mScreenWidth;
once = true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 通过设置偏移量将menu隐藏
* @param changed
* @param l
* @param t
* @param r
* @param b
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (changed) {
this.scrollTo(mMenuWidth, 0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
int scrollX = getScrollX();
if (scrollX >= mMenuWidth/2) {
smoothScrollTo(mMenuWidth, 0);
}else if (scrollX < mMenuWidth) {
smoothScrollTo(0, 0);
}
return true;
}
return super.onTouchEvent(ev);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
float scale = 1.0f * l / mMenuWidth; // 1~0
float scaleContent = 1f - (1 - scale) * 0.3f;// 1~0.7
ObjectAnimator.ofFloat(mMenu, "translationX", mMenuWidth*scale*0.7f).setDuration(0).start();
mContent.setPivotX(0);
mContent.setPivotY(mContent.getHeight() / 2);
ObjectAnimator.ofFloat(mContent, "scaleX", scaleContent).setDuration(0).start();
ObjectAnimator.ofFloat(mContent, "scaleY", scaleContent).setDuration(0).start();
mMenu.setPivotX(0);
mMenu.setPivotY(mMenu.getHeight() / 2);
ObjectAnimator.ofFloat(mMenu, "scaleX", 1.7f-scaleContent).setDuration(0).start();
ObjectAnimator.ofFloat(mMenu, "scaleY", 1.7f-scaleContent).setDuration(0).start();
}
}
布局文件