先上图,这是右侧                                       

       

  这是顶部 

  

左边和下边的都类似,就不放图了,支持简单的手势和代码控制

在搞作业的时候需要这样的一个侧边栏功能,能够推挤主屏幕,不是DrawerLayout那种,百度找了好久,只发现一种android近版本中给出的一个Slidingpanelayout的布局,这个布局效果和上图这个类似,唯一不好的就是只有左侧边栏,(或者我没发现有其他设置)于是想到重写这个Slidingpanelayout的例子,打开源代码,发现里面写的太高深,看不懂。

如果Slidingpanelayout左侧栏可以满足就不用往下看了,在build.gradle文件导入包的地方加一行:

implementation 'androidx.slidingpanelayout:slidingpanelayout:1.0.0'

直接使用就好,它的布局里只能放两个View,第一个是左侧栏内容,第二个为主页面

源码注释开头:

SlidingPaneLayout provides a horizontal, multi-pane layout for use at the top level of a UI. A left (or first) pane is treated as a content list or browser, subordinate to a primary detail view for displaying content.

SlidingPaneLayout提供了一个水平的、多窗格的布局,用于UI的顶层。左(或第一个)窗格被视为内容列表或浏览器,从属于显示内容的主要详细视图。

百度多次无果,决定自己造一个。

自定义的这个布局比较简陋,只实现了我需要的一点点功能,比如侧边栏展开让主页面变暗色,或者拖拽着边框可以拉拽这样的功能实现比较麻烦,也比较鸡肋,需要的话可以自行尝试添加。话不多说上代码:

在styles.xml文件中添加如下代码:

                                        

然后java代码:

import android.animation.ObjectAnimator;import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.animation.AccelerateDecelerateInterpolator;public class MySideBarLayout  extends ViewGroup {    private int position = 3;//默认右侧栏    private int move = 0;//记录需要滑动的量    private boolean isopen = false;//打开状态    private boolean ishead=false;//判断滑动趋势是否合格    private float lastX = 0;//记录手指在屏幕中的X    private float lastY = 0;//记录手指在屏幕中的Y    private float countmove = 0;//记录累计滑动量X    //实例化一个监听       public MySideBarLayout(Context context, AttributeSet attrs) {        super(context, attrs);        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MySideBarLayout);        position = typedArray.getInteger(R.styleable.MySideBarLayout_position, 3);        typedArray.recycle();    }    public void setOnChangeListener(OnChangeListener onChangeListener1){        onChangeListener=onChangeListener1;    }    //打开侧边栏    public void openBar() {        if (!isopen) {            onChangeListener.Onchanged(true);            setMoveAnim(move, getChildAt(0));            setMoveAnim(move, getChildAt(1));            isopen = true;        }    }    //关闭侧边栏    public void closeBar() {        if (isopen) {            onChangeListener.Onchanged(false);            setMoveAnim(0, getChildAt(0));            setMoveAnim(0, getChildAt(1));            isopen = false;        }    }    //返回侧边栏的状态    public boolean isOpen() {        return isopen;    }          //调用方法启动侧边栏的动画    private void setMoveAnim(float distance, View view) {        ObjectAnimator ro;        if (position == 1 || position == 4) {            ro = ObjectAnimator.ofFloat(view, "translationY", distance).setDuration(300);        } else {            ro = ObjectAnimator.ofFloat(view, "translationX", distance).setDuration(300);        }        ro.setInterpolator(new AccelerateDecelerateInterpolator());        ro.start();    }    //手指滑动侧边栏的动画,与上面那个没什么区别,只是时间不一样,手动的快一丢丢    private void setMoveAnimself(float distance, View view) {        ObjectAnimator ro;        if (position == 1 || position == 4) {            ro = ObjectAnimator.ofFloat(view, "translationY", distance).setDuration(150);        } else {            ro = ObjectAnimator.ofFloat(view, "translationX", distance).setDuration(150);        }        ro.setInterpolator(new AccelerateDecelerateInterpolator());        ro.start();    }     //根据子view确定布局本身的大小    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        measureChildren(widthMeasureSpec, heightMeasureSpec);        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int width = MeasureSpec.getSize(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int height = MeasureSpec.getSize(heightMeasureSpec);        if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {            int groupWidth = getMaxWidth();            int groupHeight = getTotalHeight();            setMeasuredDimension(groupWidth, groupHeight);        } else if (widthMode == MeasureSpec.AT_MOST) {            setMeasuredDimension(getMaxWidth(), height);        } else if (heightMode == MeasureSpec.AT_MOST) {            setMeasuredDimension(width, getTotalHeight());        }    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        int pw = r - l;        int ph = b - t;        View v1 = getChildAt(0);        v1.layout(0, 0, pw, ph);        View v2 = getChildAt(1);        int vw = v2.getMeasuredWidth();        int vh = v2.getMeasuredHeight();        if (position == 1) {            move = vh;            v2.layout(0, -vh, pw, 0);        } else if (position == 2) {            move = vw;            v2.layout(-vw, 0, 0, ph);        } else if (position == 3) {            move = -vw;            v2.layout(pw, 0, pw + vw, ph);        } else if (position == 4) {            move = -vh;            v2.layout(0, ph, pw, ph + vh);        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                lastX = event.getRawX();                lastY = event.getRawY();                break;            case MotionEvent.ACTION_MOVE:                float vx = event.getRawX() - lastX;                float vy = event.getRawY() - lastY;                if (position == 1) {                    if(Math.abs(vy)>Math.abs(2*vx)) {                        if (isopen && vy < 0) {                            countmove = vy;                            ishead = true;                        } else if (!isopen && vy > 0) {                            countmove = vy;                            ishead = true;                        }                    }                } else if (position == 2) {                    if(Math.abs(vx)>Math.abs(2*vy)) {                        if (isopen && vx < 0) {                            countmove = vx;                            ishead = true;                        } else if (!isopen && vx > 0) {                            countmove = vx;                            ishead = true;                        }                    }                } else if (position == 3) {                    if(Math.abs(vx)>Math.abs(2*vy)) {                        if (isopen && vx > 0) {                            countmove = vx;                            ishead = true;                        } else if (!isopen && vx < 0) {                            countmove = vx;                            ishead = true;                        }                    }                } else if (position == 4) {                    if(Math.abs(vy)>Math.abs(2*vx)) {                        if (isopen && vy > 0) {                            countmove = vy;                            ishead = true;                        } else if (!isopen && vy < 0) {                            countmove = vy;                            ishead = true;                        }                    }                }                break;            case MotionEvent.ACTION_UP:                if (Math.abs(countmove) > Math.abs(move) / 2 && !isopen&&ishead) {                    isopen = true;                    ishead=false;                    onChangeListener.Onchanged(true);                    setMoveAnimself(move, getChildAt(0));                    setMoveAnimself(move, getChildAt(1));                } else if (Math.abs(countmove) > Math.abs(move) / 2 && isopen&&ishead) {                    isopen = false;                    ishead=false;                    onChangeListener.Onchanged(false);                    setMoveAnimself(0, getChildAt(0));                    setMoveAnimself(0, getChildAt(1));                }                break;        }        return true;    }    private int getMaxWidth() {        int count = getChildCount();        int maxWidth = 0;        for (int i = 0; i < count; i++) {            int currentWidth = getChildAt(i).getMeasuredWidth();            if (maxWidth < currentWidth) {                maxWidth = currentWidth;            }        }        return maxWidth;    }    private int getTotalHeight() {        int count = getChildCount();        int totalHeight = 0;        for (int i = 0; i < count; i++) {            totalHeight += getChildAt(i).getMeasuredHeight();        }        return totalHeight;    }    private OnChangeListener onChangeListener=new OnChangeListener() {        @Override        public void Onchanged(boolean status) {        }    };    public  interface OnChangeListener{        void Onchanged(boolean status);    }}

使用方法:第一个view为主页面,第二个为侧页面。

中调用

app:position="top"

提供四个选项 : top , left , right , bottom    

<包名.MySideBarLayout    android:id="@+id/sidelayout"    android:layout_width="match_parent"    android:layout_height="match_parent"    app:position="top"    >                     

java 代码中我实现了几个简单的方法:

openBar()打开侧栏

closeBar()关闭侧栏

isOpen()  获取侧边栏的状态

setOnChangeListener(OnChangeListener onChangeListener1)设置侧边栏变化监听

这里注意监听名,MySideBarLayout.OnChangeListener()是我在包内自定义的监听

mysidebarlayout.setOnChangeListener(new MySideBarLayout.OnChangeListener() {    @Override    public void Onchanged(boolean status) {        if(status){            textview.setText("侧边栏已打开");        }else{            textview.setText("侧边栏已关闭");        }    }});

就这么简单就OK了,如果需要在这个布局里同时能滑动四个侧边栏,也可以实现的,重写这个onlayout........需要的话自行解决吧,东西比较简陋,有什么问题可以留言建议,我再调整调整,一起学习学习

 

 

 

 

更多相关文章

  1. 简单的Android(安卓)XML布局使用
  2. 38、Android编写应用-使用布局编辑器Layout Editor构建界面
  3. android实现3D效果翻页
  4. Android(安卓)仿微信点赞和评论弹出框
  5. Android中将控件放到线性布局的任意位置(一)
  6. Android(安卓)FrameLayout布局
  7. Android解决SurfaceView预览Camera拉伸问题
  8. 关于 Android(安卓)Fragment的官方说明文档
  9. Android界面布局编程

随机推荐

  1. Android实现信号强度监听的方法
  2. Android 用一个监听器实现多个监听
  3. android的dip,dp,px,in,mm,pt,sp
  4. Android Studio中添加对HttpClient的支持
  5. Android Studio 配置使用 AIDL 跨应用通
  6. Android(安卓)AndroidStaggeredGrid 开源
  7. 第七章 布局
  8. 总结Android中TabActivity 的使用方法
  9. Android 带动画的底部弹出视图
  10. android系统编译adt插件