自定义左右滑动菜单

存一个自定义滑动菜单:

记一些关键的函数作用:

1.定义一个FrameLayout fm,fm.measure(width,height)代表定义这个fm的长和宽。
2.onMeasure()用于测量父Layout里面的各个layout,onLayout用于布局父Layout里面的各个layout。
3.实际操作滑动距离的时候用下面的代码:

int scrollX = getScrollX();
                    int dX = (int) ev.getX() - point.x;
                    int finalX = 0;
                    int exX = scrollX - dX;
                    if(exX > 0){
                        finalX = Math.max(exX,-leftFrame.getMeasuredWidth());          //最多只能滑到右边的边界
                        scrollTo(finalX,0);                 //滑动操作
                    }
                    else{
                        finalX = Math.min(exX,rightFrame.getMeasuredWidth());          //最多只能滑到左边的边界
                        scrollTo(finalX,0);
                    }

4.更新了蒙版效果,在滑倒其他页面时,主页面会进行灰度的渐变。
5.添加了事件监听。
MainActivity.Java

package com.example.a53125.slidingrelativelayouttest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    private MainUI mainUI;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mainUI = new MainUI(this);
        setContentView(mainUI);
    }
}

MainUI.Java

package com.example.a53125.slidingrelativelayouttest;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Point;
import android.support.annotation.Px;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.Scroller;



/**
 * Created by 53125 on 2017/8/16.
 */

public class MainUI extends RelativeLayout {
    @android.support.annotation.IdRes
    int LEFT_ID = 0xaabbcc;
    @android.support.annotation.IdRes
    int MID_ID = 2222;
    @android.support.annotation.IdRes
    int RIGHT_ID = 3333;
    private Context context;
    private FrameLayout middleFrame;
    private FrameLayout leftFrame;
    private FrameLayout rightFrame;
    private FrameLayout maskFrame;
    private Scroller scroller;
//    public static int LEFT_ID = 0xaabbcc;
//    public final int MID_ID = 2222;
//    public final int RIGHT_ID = 3333;

    public MainUI(Context context) {
        super(context);
        this.context = context;
        initView(context);
    }

    public MainUI(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }

    public void initView(Context context){
        scroller = new Scroller(context,new DecelerateInterpolator());
        middleFrame = new FrameLayout(context);
        leftFrame = new FrameLayout(context);
        rightFrame = new FrameLayout(context);
        maskFrame = new FrameLayout(context);
        middleFrame.setBackgroundColor(Color.GREEN);
        leftFrame.setBackgroundColor(Color.YELLOW);
        rightFrame.setBackgroundColor(Color.YELLOW);
        maskFrame.setBackgroundColor(0x88000000);
        maskFrame.setAlpha(0);
        leftFrame.setId(LEFT_ID);
        middleFrame.setId(MID_ID);
        rightFrame.setId(RIGHT_ID);
        addView(leftFrame);
        addView(middleFrame);
        addView(rightFrame);
        addView(maskFrame);
    }

    @Override
    public void scrollTo(@Px int x, @Px int y) {
        super.scrollTo(x, y);
        int scr = Math.abs(getScrollX());
        float alpha = scr/(float) leftFrame.getMeasuredWidth();
        maskFrame.setAlpha(alpha);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        middleFrame.measure(widthMeasureSpec,heightMeasureSpec);
        maskFrame.measure(widthMeasureSpec,heightMeasureSpec);
        int Screen_Width = MeasureSpec.getSize(widthMeasureSpec);
//        System.out.println("widthMeasureSpec:"+widthMeasureSpec);
//        System.out.println("Screen_Width"+Screen_Width);
        int Left_Width = MeasureSpec.makeMeasureSpec((int)(Screen_Width*0.8f),MeasureSpec.EXACTLY);
        leftFrame.measure(Left_Width,heightMeasureSpec);
        rightFrame.measure(Left_Width,heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        middleFrame.layout(l, t, r, b);
        maskFrame.layout(l, t, r, b);
        leftFrame.layout(l-leftFrame.getMeasuredWidth(), t, r, b);
        rightFrame.layout(l+middleFrame.getMeasuredWidth(), t, r+rightFrame.getMeasuredWidth(), b);
    }

    private int state = 0;
    private boolean stateSlidingLeftRight = false;        //是否左右滑动
    private boolean stateSlidingUpDown = false;        //是否上下滑动
    private int TEST_DIS = 20;             //滑动判定的最小距离
    Point point = new Point();

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
//        System.out.println("Click successfully!");
//        System.out.println("LeftWidth:"+leftFrame.getMeasuredWidth());
//        System.out.println("MidWidth:"+middleFrame.getMeasuredWidth());
        if(!(state == 1)){

            getState(ev);
//            System.out.println("stateSlidingLeftRight:"+stateSlidingLeftRight);
            return true;                  //一定要返回true,否则的话不会进行滑动操作
        }
        if(stateSlidingUpDown){                    //用于初始化横向滑动的状态,便于接着上次再次滑动
            stateSlidingLeftRight = false;
            state = 0;
        }
        if(stateSlidingLeftRight){
            System.out.println("Sliding successfully!");
            switch (ev.getActionMasked()){
                case MotionEvent.ACTION_MOVE:
                    int scrollX = getScrollX();
                    int dX = (int) ev.getX() - point.x;
                    int finalX = 0;
                    int exX = scrollX - dX;
                    if(exX > 0){
                        finalX = Math.max(exX,-leftFrame.getMeasuredWidth());          //最多只能滑到右边的边界
                        scrollTo(finalX,0);                 //滑动操作
                    }
                    else{
                        finalX = Math.min(exX,rightFrame.getMeasuredWidth());          //最多只能滑到左边的边界
                        scrollTo(finalX,0);
                    }
                    point.x = (int) ev.getX();                 //保存点,用于下一次滑动
                    point.y = (int) ev.getY();
                    break;
                case MotionEvent.ACTION_UP:              //用于初始化横向滑动的状态,便于接着上次再次滑动
                case MotionEvent.ACTION_CANCEL:         //用于初始化横向滑动的状态,便于接着上次再次滑动
                    int scroll = getScrollX();
                    if(Math.abs(scroll) > leftFrame.getMeasuredWidth() >>1){
                        if(scroll < 0){
                            scroller.startScroll(scroll,0,-leftFrame.getMeasuredWidth()-scroll,0);
                        }
                        else{
                            scroller.startScroll(scroll,0,leftFrame.getMeasuredWidth()-scroll,0);
                        }
                    }
                    else{
                        scroller.startScroll(scroll,0,-scroll,0);
                    }
                    invalidate();
                    stateSlidingLeftRight = false;
                    state = 0;
                    break;
                default:break;
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if(!scroller.computeScrollOffset()){
            return;
        }
        int tempX = scroller.getCurrX();
        scrollTo(tempX,0);
    }

    private void getState(MotionEvent ev) {
        switch (ev.getActionMasked()){
            case MotionEvent.ACTION_UP:        //手指抬起后触发
                state = 0;
                stateSlidingLeftRight = false;
                stateSlidingUpDown = false;
                super.dispatchTouchEvent(ev);
                break;
            case MotionEvent.ACTION_DOWN:        //手指按下的一瞬间触发
                point.x = (int) ev.getX();
                point.y = (int) ev.getY();
                super.dispatchTouchEvent(ev);
                break;
            case MotionEvent.ACTION_CANCEL:      //手指滑到边界触发
                stateSlidingLeftRight = false;
                state = 0;
                dispatchTouchEvent(ev);
                break;
            case MotionEvent.ACTION_MOVE:         //手指滑动触发
                int dX = Math.abs((int)ev.getX() - point.x);
                int dY = Math.abs((int)ev.getY() - point.y);
                if(dX > dY && dX > TEST_DIS){         //滑动举例大于TEST_DIS才算滑动
                    stateSlidingLeftRight = true;
                    stateSlidingUpDown = false;
                    state = 1;
                    point.x = (int) ev.getX();
                    point.y = (int) ev.getY();
                }else if(dX < dY && dY > TEST_DIS){
                    stateSlidingUpDown = true;
                    stateSlidingLeftRight = false;
                    state = 1;
                    point.x = (int) ev.getX();          //记录点用于下次滑动
                    point.y = (int) ev.getY();
                }
                break;

        }
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现可滑动的侧边栏,可以使用 Ant Design 的 Layout 组件。具体步骤如下: 1. 引入 Layout 组件 首先,在组件中引入 Layout 组件: ```jsx import { Layout } from 'antd'; const { Sider, Content } = Layout; ``` 2. 创建 Sider 和 Content 使用 Sider 组件创建侧边栏,使用 Content 组件创建主内容区域。例如: ```jsx <Layout> <Sider width={200} style={{ background: '#fff' }}> 左侧菜单 </Sider> <Content style={{ padding: '0 24px', minHeight: 280 }}> 主内容区域 </Content> </Layout> ``` 其中,Sider 的 width 属性设置侧边栏宽度,Content 的 style 属性设置主内容区域样式。 3. 设置 Sider 的可滑动 为了使 Sider 可以滑动,需要为其添加 trigger 和 collapsible 属性。例如: ```jsx <Sider width={200} style={{ background: '#fff' }} trigger={null} collapsible collapsed={this.state.collapsed}> 左侧菜单 </Sider> ``` 其中,trigger={null} 表示隐藏默认的 trigger,collapsible 表示是否可收缩,collapsed 则表示是否默认收缩。 4. 设置 trigger 如果需要显示自定义的 trigger,可以在 Sider 中添加一个按钮,并设置 trigger={this.trigger()},其中 trigger() 返回一个函数,用于切换侧边栏的收缩状态。 ```jsx <Sider width={200} style={{ background: '#fff' }} trigger={this.trigger()} collapsible collapsed={this.state.collapsed}> 左侧菜单 </Sider> trigger = () => { return ( <div onClick={this.toggle}> <Icon type={this.state.collapsed ? 'menu-unfold' : 'menu-fold'} /> </div> ); }; toggle = () => { this.setState({ collapsed: !this.state.collapsed, }); }; ``` 这样就可以创建一个可滑动的侧边栏了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值