失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 仿SlidingMenu自定义QQ侧滑菜单

仿SlidingMenu自定义QQ侧滑菜单

时间:2020-12-02 06:59:26

相关推荐

仿SlidingMenu自定义QQ侧滑菜单

不多说,先上图

主页面 侧滑页面

一、首先我们要自定义一个DragLayout继承自FrameLayout

import android.content.Context;import android.graphics.Color;import android.graphics.PorterDuff;import android.support.v4.view.ViewCompat;import android.support.v4.widget.ViewDragHelper;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.FrameLayout;import com.nineoldandroids.view.ViewHelper;/*** =========================================* 版权所有 违法必究* 作者: huangxiaoguo*/public class DragLayout extends FrameLayout {private ViewDragHelper mViewDragHelper;private ViewGroup mLeftPanel;private ViewGroup mMainPanel;private int mWidth;private int mHeight;private int mRange;private DragState state = DragState.CLOSE;//默认关闭状态public enum DragState {OPEN, CLOSE, DRAGING}private OnDragChangeListener onDragChangeListener;public OnDragChangeListener getOnDragChangeListener() {return onDragChangeListener;}public void setOnDragChangeListener(OnDragChangeListener onDragChangeListener) {this.onDragChangeListener = onDragChangeListener;}public interface OnDragChangeListener {void onOpen();void onClose();void onDraging(float percent);}public DragLayout(Context context) {this(context, null);}public DragLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public DragLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//1 .初始化 ViewDragHelpermViewDragHelper = ViewDragHelper.create(this, callback);}//2 事件转交 mViewDragHelper@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {return mViewDragHelper.shouldInterceptTouchEvent(ev);}// 转交touch事件@Overridepublic boolean onTouchEvent(MotionEvent event) {try {mViewDragHelper.processTouchEvent(event);} catch (Exception e) {e.printStackTrace();}return true;}// onmeasure 方法后调用@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mWidth = getMeasuredWidth();mHeight = getMeasuredHeight();//左边面板的 范围// mRange = (int) (mWidth * 0.6f);mRange = (int) (mWidth * 0.8f);}//xml --->view@Overrideprotected void onFinishInflate() {super.onFinishInflate();//健壮性判断mLeftPanel = (ViewGroup) getChildAt(0);mMainPanel = (ViewGroup) getChildAt(1);}// mViewDragHelper 解析touch事件后 有的 回调ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {// 返回值 决定是否可以滑动@Overridepublic boolean tryCaptureView(View child, int pointerId) {return true;}// 修正 还没有真正的移动@Overridepublic int clampViewPositionHorizontal(View child, int left, int dx) {if (child == mMainPanel) { //拖动是mMainPanelleft = fixedLeft(left);}return left;}/*** 修正主面板位置* @param left* @return*/private int fixedLeft(int left) {if (left < 0) {left = 0;} else if (left > mRange) {left = mRange;}return left;}// 获取横向拖动范围 不决定实际的拖动范围@Overridepublic int getViewHorizontalDragRange(View child) {return mRange;}// 实际拖动的时候调用 1. 添加伴随动画 2. 更新状态 3.添加回调@Overridepublic void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {if (changedView == mLeftPanel) { //如果拖动的是 changedView . 按到 之前的位置//System.out.println("mLeftPanel>>>" + dx);mLeftPanel.layout(0, 0, mWidth, mHeight);// 只要 mLeftPanel移动 将瞬间变化交给mMainPanelint currentLeft = mMainPanel.getLeft();int newLeft = currentLeft + dx;//重新 对位置修正newLeft = fixedLeft(newLeft);mMainPanel.layout(newLeft, 0, newLeft + mWidth, mHeight);}// 伴随动画 2.状态更新 3.添加回调dispatchDragEvent(mMainPanel.getLeft());//手动刷新invalidate();}//当手指抬起的时候调用@Overridepublic void onViewReleased(View releasedChild, float xvel, float yvel) {//releasedChild 释放的子view//xvel 释放时横向的速度 向左 - 向右 + 0//yvel 释放时纵向的速度if (xvel == 0 && mMainPanel.getLeft() > mRange * 0.5f) {open();} else if (xvel > 0) {open();} else {close();}}};/*** @param left 主面板 的 左边的坐标*/private void dispatchDragEvent(int left) {// 0.0 -- 1.0float percent = left * 1.0f / mRange;// 10 / 111 = 0;animView(percent);DragState preState = state;state = updateState(percent);if (onDragChangeListener != null) {onDragChangeListener.onDraging(percent);if (state != preState) {if (state == DragState.OPEN) {onDragChangeListener.onOpen();} else if (state == DragState.CLOSE) {onDragChangeListener.onClose();}}}}/*** 更新状态** @param percent* @return*/private DragState updateState(float percent) {if (percent == 0) {return DragState.CLOSE;} else if (percent == 1) {return DragState.OPEN;}return DragState.DRAGING;}/*** 伴随动画** @param percent*/private void animView(float percent) {// 1.0-----0.80.8+(1-percent)*0.2//1. 主面板 缩小动画// mMainPanel.setScaleX(0.8f+(1-percent)*0.2f);// mMainPanel.setScaleY(0.8f+(1-percent)*0.2f);// ViewHelper.setScaleX(mMainPanel, evaluate(percent, 1.0f, 0.8f));// ViewHelper.setScaleY(mMainPanel, evaluate(percent, 1.0f, 0.8f));ViewHelper.setScaleX(mMainPanel, evaluate(percent, 1.0f, 1.0f));ViewHelper.setScaleY(mMainPanel, evaluate(percent, 1.0f, 1.0f));// 2 左边面板 缩放动画 平移动画//0.7---1.0// ViewHelper.setScaleX(mLeftPanel, evaluate(percent, 0.7f, 1.0f));// ViewHelper.setScaleY(mLeftPanel, evaluate(percent, 0.7f, 1.0f));ViewHelper.setScaleX(mLeftPanel, evaluate(percent, 1.0f, 1.0f));ViewHelper.setScaleY(mLeftPanel, evaluate(percent, 1.0f, 1.0f));//横向平移ViewHelper.setTranslationX(mLeftPanel, evaluate(percent, -mWidth * 0.7f, 0));// 3 背景 黑色 -- -透明色getBackground().setColorFilter((Integer) evaluateColor(percent, Color.BLACK, Color.TRANSPARENT), PorterDuff.Mode.SRC_OVER);}public Float evaluate(float fraction, Number startValue, Number endValue) {float startFloat = startValue.floatValue();return startFloat + fraction * (endValue.floatValue() - startFloat);}/*** 颜色的估值器 @{link ArgbEvaluator}** @param fraction* @param startValue* @param endValue* @return*/public Object evaluateColor(float fraction, Object startValue, Object endValue) {int startInt = (Integer) startValue;int startA = (startInt >> 24) & 0xff;int startR = (startInt >> 16) & 0xff;int startG = (startInt >> 8) & 0xff;int startB = startInt & 0xff;int endInt = (Integer) endValue;int endA = (endInt >> 24) & 0xff;int endR = (endInt >> 16) & 0xff;int endG = (endInt >> 8) & 0xff;int endB = endInt & 0xff;return (int) ((startA + (int) (fraction * (endA - startA))) << 24) |(int) ((startR + (int) (fraction * (endR - startR))) << 16) |(int) ((startG + (int) (fraction * (endG - startG))) << 8) |(int) ((startB + (int) (fraction * (endB - startB))));}// 和 ondraw 方法@Overridepublic void computeScroll() {puteScroll();//是否继续触发动画if (mViewDragHelper.continueSettling(true)) {// 触发动画 执行动画ViewCompat.postInvalidateOnAnimation(this);}}public void open(boolean isSmooth) {int finalLeft = mRange;if (isSmooth) {//返回值决定 是否触发动画boolean b = mViewDragHelper.smoothSlideViewTo(mMainPanel, finalLeft, 0);if (b) {// 触发动画 执行动画ViewCompat.postInvalidateOnAnimation(this);}} else {mMainPanel.layout(finalLeft, 0, finalLeft + mWidth, mHeight);}}/*** 打开*/public void open() {open(true);//默认平滑打开}public void close(boolean isSmooth) {int finalLeft = 0;if (isSmooth) {//返回值决定 是否触发动画boolean b = mViewDragHelper.smoothSlideViewTo(mMainPanel, finalLeft, 0);if (b) {// 触发动画 执行动画ViewCompat.postInvalidateOnAnimation(this);}} else {mMainPanel.layout(finalLeft, 0, finalLeft + mWidth, mHeight);}}/*** 关闭*/public void close() {close(true);//默认平滑关闭}}

然后再xml中进行页面布局

<?xml version="1.0" encoding="utf-8"?><com.example.draglayout.view.DragLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/draglayout"android:background="@color/colorPrimary"><LinearLayout android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:paddingBottom="50dp"android:paddingLeft="16dp"android:paddingRight="50dp"android:paddingTop="50dp"><ImageView android:layout_width="55dp"android:layout_height="55dp"android:src="@mipmap/icon_head" /><android.support.v7.widget.RecyclerView android:id="@+id/left_recyclerView"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout><LinearLayout android:layout_width="match_parent"android:layout_height="match_parent"android:background="#fff"android:orientation="vertical"><RelativeLayout android:layout_width="match_parent"android:layout_height="50dp"android:background="#4a6ff4"android:gravity="center_vertical"><ImageViewandroid:id="@+id/iv_icon"android:layout_width="35dp"android:layout_height="35dp"android:layout_marginLeft="8dp"android:src="@mipmap/icon_head" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="标题"android:textColor="#ffffff"android:textSize="20dp" /></RelativeLayout><android.support.v7.widget.RecyclerView android:id="@+id/main_recyclerView"android:layout_width="match_parent"android:layout_height="match_parent"android:cacheColorHint="@android:color/transparent"/></LinearLayout></com.example.draglayout.view.DragLayout>

然后就是MainActivity中的操作了

import android.content.Context;import android.os.Bundle;import android.support.v4.content.ContextCompat;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.View;import android.widget.ImageView;import com.example.draglayout.adapter.MyAdapter;import com.example.draglayout.utils.ToastUtil;import com.example.draglayout.view.DragLayout;import com.example.draglayout.view.RecycleViewDivider;import java.util.concurrent.CopyOnWriteArrayList;public class MainActivity extends AppCompatActivity {private RecyclerView left_recyclerView;private ImageView iv_icon;private RecyclerView main_recyclerView;private LinearLayoutManager manager;private Context mContext;private LinearLayoutManager manager1;private MyAdapter myAdapter;private MyAdapter myAdapter1;private DragLayout dragLayout;private CopyOnWriteArrayList<String> names = new CopyOnWriteArrayList<>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mContext = this;init();initData();initView();initListener();}private void init() {for (int i = 0; i < 50; i++) {names.add("huangxiaoguo" + i);}}private void initData() {left_recyclerView = (RecyclerView) findViewById(R.id.left_recyclerView);iv_icon = (ImageView) findViewById(R.id.iv_icon);main_recyclerView = (RecyclerView) findViewById(R.id.main_recyclerView);dragLayout = (DragLayout) findViewById(R.id.draglayout);manager = new LinearLayoutManager(mContext);manager.setOrientation(LinearLayoutManager.VERTICAL);left_recyclerView.setLayoutManager(manager);int mColor = ContextCompat.getColor(mContext, R.color.light_gray);left_recyclerView.addItemDecoration(new RecycleViewDivider(mContext, LinearLayoutManager.HORIZONTAL, 2, mColor));manager1 = new LinearLayoutManager(mContext);manager1.setOrientation(LinearLayoutManager.VERTICAL);main_recyclerView.setLayoutManager(manager1);int mColor1 = ContextCompat.getColor(mContext, R.color.light_gray);main_recyclerView.addItemDecoration(new RecycleViewDivider(mContext, LinearLayoutManager.HORIZONTAL, 2, mColor1));}private void initView() {myAdapter = new MyAdapter(mContext, names);left_recyclerView.setAdapter(myAdapter);myAdapter1 = new MyAdapter(mContext, names);main_recyclerView.setAdapter(myAdapter1);dragLayout.setOnDragChangeListener(new DragLayout.OnDragChangeListener() {@Overridepublic void onOpen() {ToastUtil.showToast(MainActivity.this, "打开");}@Overridepublic void onClose() {ToastUtil.showToast(MainActivity.this, "关闭");}@Overridepublic void onDraging(float percent) {ToastUtil.showToast(MainActivity.this, "偏移距离= " + percent);}});}private void initListener() {myAdapter1.setOnItemClickListener(new MyAdapter.OnItemClickListener() {@Overridepublic void OnClick(int position) {ToastUtil.showToast(MainActivity.this, names.get(position));dragLayout.close();}});iv_icon.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {dragLayout.close();}});}}

好了这样局基本实现了

Demo下载地址:/download/huangxiaoguo1/9732303

如果觉得《仿SlidingMenu自定义QQ侧滑菜单》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。