仿SlidingMenu自定义QQ侧滑菜单
来源:互联网 发布:mysql 5.5.23.tar.gz 编辑:程序博客网 时间:2024/04/29 06:16
不多说,先上图
- 主页面
- 侧滑页面
一、首先我们要自定义一个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 .初始化 ViewDragHelper mViewDragHelper = ViewDragHelper.create(this, callback); } //2 事件转交 mViewDragHelper @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return mViewDragHelper.shouldInterceptTouchEvent(ev); } // 转交touch事件 @Override public boolean onTouchEvent(MotionEvent event) { try { mViewDragHelper.processTouchEvent(event); } catch (Exception e) { e.printStackTrace(); } return true; } // onmeasure 方法后调用 @Override protected 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 @Override protected void onFinishInflate() { super.onFinishInflate(); //健壮性判断 mLeftPanel = (ViewGroup) getChildAt(0); mMainPanel = (ViewGroup) getChildAt(1); } // mViewDragHelper 解析touch事件后 有的 回调 ViewDragHelper.Callback callback = new ViewDragHelper.Callback() { // 返回值 决定是否可以滑动 @Override public boolean tryCaptureView(View child, int pointerId) { return true; } // 修正 还没有真正的移动 @Override public int clampViewPositionHorizontal(View child, int left, int dx) { if (child == mMainPanel) { //拖动是mMainPanel left = 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; } // 获取横向拖动范围 不决定实际的拖动范围 @Override public int getViewHorizontalDragRange(View child) { return mRange; } // 实际拖动的时候调用 1. 添加伴随动画 2. 更新状态 3.添加回调 @Override public 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移动 将瞬间变化交给mMainPanel int currentLeft = mMainPanel.getLeft(); int newLeft = currentLeft + dx; //重新 对位置修正 newLeft = fixedLeft(newLeft); mMainPanel.layout(newLeft, 0, newLeft + mWidth, mHeight); } // 伴随动画 2.状态更新 3.添加回调 dispatchDragEvent(mMainPanel.getLeft()); //手动刷新 invalidate(); } //当手指抬起的时候调用 @Override public 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.0 float 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.8 0.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 方法 @Override public void computeScroll() { super.computeScroll(); //是否继续触发动画 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="http://schemas.android.com/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"> <ImageView android:id="@+id/iv_icon" android:layout_width="35dp" android:layout_height="35dp" android:layout_marginLeft="8dp" android:src="@mipmap/icon_head" /> <TextView android: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<>(); @Override protected 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() { @Override public void onOpen() { ToastUtil.showToast(MainActivity.this, "打开"); } @Override public void onClose() { ToastUtil.showToast(MainActivity.this, "关闭"); } @Override public void onDraging(float percent) { ToastUtil.showToast(MainActivity.this, "偏移距离= " + percent); } }); } private void initListener() { myAdapter1.setOnItemClickListener(new MyAdapter.OnItemClickListener() { @Override public void OnClick(int position) { ToastUtil.showToast(MainActivity.this, names.get(position)); dragLayout.close(); } }); iv_icon.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { dragLayout.close(); } }); }}
好了这样局基本实现了
Demo下载地址:http://download.csdn.net/download/huangxiaoguo1/9732303
0 0
- 仿SlidingMenu自定义QQ侧滑菜单
- 自定义侧滑菜单SlidingMenu
- 动态添加Fragment及侧滑菜单SlidingMenu仿QQ界面
- 仿QQ slidingmenu 自定义属性 自定义控件
- 自定义viewgroup 继承 FrameLayout 仿QQ侧滑菜单
- Android自定义View之仿QQ侧滑菜单实现
- 自定义view 之 仿QQ侧滑菜单
- 仿QQ侧滑菜单
- 仿QQ侧滑菜单
- 仿 qq 侧滑菜单
- 仿QQ侧滑菜单
- 仿QQ侧滑菜单
- 仿QQ侧滑菜单
- 仿QQ侧滑菜单
- 最简单的基于SlidingMenu仿QQ侧滑效果
- 修改slidingmenu仿QQ5.0侧滑菜单
- 左右滑动菜单 slidingmenu 仿人人 QQ等
- 仿qq最新侧滑菜单
- 使用java8的lambada表达式按照一定的条件对查出的数据进行过滤
- 使用NDK api调用AssetManager
- 一个玩英雄联盟的java程序员这样忏悔!不!是发誓!
- 复制表A的某一天的数据到表A,并修改其一列值的SQL
- gulp合并压缩很多js文件时,报intermediate value is not a function错误解决
- 仿SlidingMenu自定义QQ侧滑菜单
- Linux curl命令详解
- 51nod-1429 巧克力
- php中mysql_connect与mysql_pconnect的区别
- 逻辑回归
- Spring IOC和AOP 原理彻底搞懂
- Android ViewDragHelper完全解析 自定义ViewGroup神器
- App 后台架构设计方案 设计思想与最佳实践
- linux应用之_文件IO前世今生