自定义侧滑组件+自定义属性

来源:互联网 发布:各国战争潜力知乎 编辑:程序博客网 时间:2024/06/06 04:20

继承HorizontalScrollView,通过添加各种方法,自定义实现各种侧滑效果


先看xml布局文件

<?xml version="1.0" encoding="utf-8"?><com.example.administrator.slidingmenu.widget.SlidingMenu     xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    xmlns:app="http://schemas.android.com/apk/res-auto"    <!--自定义属性的赋值-->   app:left_off_width="300"   tools:context="com.example.administrator.slidingmenu.MainActivity">    <com.example.administrator.slidingmenu.widget.OrdetDrawLinearLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="horizontal">        <LinearLayout            android:id="@+id/teach_left_menu"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:orientation="vertical"            android:background="@color/colorAccent"            >            <TextView                android:layout_width="match_parent"                android:layout_height="match_parent"                android:gravity="center"                android:text="左侧菜单"                />        </LinearLayout>        <LinearLayout            android:id="@+id/teach_main_content"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:gravity="center"            android:orientation="vertical"            android:background="@color/colorPrimary">            <ImageView                android:layout_width="200dp"                android:layout_height="200dp"                android:src="@mipmap/ic_launcher"                />        </LinearLayout>    </com.example.administrator.slidingmenu.widget.OrdetDrawLinearLayout></com.example.administrator.slidingmenu.widget.SlidingMenu>




再看java代码。自定义侧滑组件的类SlidingMenu继承于HorizoltalScrollView

package com.example.administrator.slidingmenu.widget;import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.HorizontalScrollView;import android.widget.LinearLayout;import com.example.administrator.slidingmenu.R;/** * * ViewGroup 绘制流程 *         onMeasure *         onLayout *         onDraw * * *自定义属性 * 1在value下创建attrs,在其中使用<declare-styleable标签声明我们自己要为哪个View设置属性 * 2在自定义属性中创建自己的属性,指定name和format * 2在我们View的构造函数中,使用TypeArray进行属性的加载,使用完成要注意回收 * 4对我们获取的值进行使用,在xml布局中使用自定义属性 * * Created by Administrator on 2016/6/16. */public class SlidingMenu extends HorizontalScrollView{    private static final String TAG = SlidingMenu.class.getSimpleName();    private View mLeftMenu;//左侧的侧滑布局    private View mContent;//主内容布局    private int mScreenWidth;//屏幕宽度    private int leftMenuWidthOff;//当左侧菜单划出的时候屏幕的剩余宽度    private static final int MENU_DEFAULT_WIDTH_OFF=150;//指定默认值,没有更改时就是这个值    private int leftMenuWidth;//左侧菜单的宽度    private boolean isMeasure;//布局测量的标记位    private int leftMenuHaftWidth;//左侧菜单宽度的一半    public SlidingMenu(Context context) {        this(context, null);    }    /**     * 使用Inflate进来的View走两个参数的构造     * @param context     * @param attrs     */    public SlidingMenu(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        //获取屏幕宽度        mScreenWidth=getResources().getDisplayMetrics().widthPixels;        //自定义的所有属性        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SlidingMenr, defStyleAttr, 0);        leftMenuWidthOff=typedArray.getInt(R.styleable.SlidingMenr_left_off_width, MENU_DEFAULT_WIDTH_OFF);        //使用完成要回收        typedArray.recycle();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        if (!isMeasure) {            //滑动布局中的唯一的Child            LinearLayout single = (LinearLayout) getChildAt(0);            //获取左侧菜单            mLeftMenu = single.getChildAt(0);            //获取中间的内容部分            mContent = single.getChildAt(1);            //左侧的菜单宽度赋值            leftMenuWidth = mScreenWidth - leftMenuWidthOff;            //左侧菜单的一半//            leftMenuHaftWidth=leftMenuWidth/2;            leftMenuHaftWidth=leftMenuWidth >> 1;            //设置左边Menu的宽度            mLeftMenu.getLayoutParams().width = leftMenuWidth;            //设置主内容区域的宽度            mContent.getLayoutParams().width=mScreenWidth;        }        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        super.onLayout(changed, l, t, r, b);        if(changed){            //粗暴滚动            scrollTo(leftMenuWidth, 0);            isMeasure=true;        }    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_UP:                int scrollX = getScrollX();                Log.e(TAG, "onTouchEvent"+scrollX);                //滑动距离大于左侧菜单的一半                if (scrollX>leftMenuHaftWidth) {                    //显示主内容区                    //平滑滚动                    smoothScrollTo(leftMenuWidth, 0);                }else {                    //显示左侧菜单                    smoothScrollTo(0,0);                }                return true;        }        return super.onTouchEvent(ev);    }    //可以在onScrollChanged方法中添加各种动画    @Override    protected void onScrollChanged(int l, int t, int oldl, int oldt) {        super.onScrollChanged(l, t, oldl, oldt);        Log.e(TAG, "onScrollChanged: -->" + l + "---" + t);        //测试手机宽度1080,左侧菜单减少宽度150,上一步向左滚动了leftMenuWidth,所以这里初始l为1080-150=930。向左滑动l为正值        //效果:当向右滑动时,左侧菜单同时向右平移,感觉左侧菜单一直在右侧的底部        //即菜单被掩盖//        mLeftMenu.setTranslationX(l);        //主内容被掩盖。         mContent.setTranslationX(l-leftMenuWidth);    }}





当执行上面onScrollChanged方法
//主内容被掩盖。  mContent.setTranslationX(l-leftMenuWidth);
的方法的时候,会出现bug,导致内容页面完全覆盖侧滑页面,所以执行下面自定义方法,改变其Child的绘制顺序

package com.example.administrator.slidingmenu.widget;import android.content.Context;import android.util.AttributeSet;import android.widget.LinearLayout;/** * 更改View绘制的顺序 * 重写getChildDrawingOrder * 设置Child绘制顺序可以更改(启用绘制顺序) * * * Created by Administrator on 2016/6/16. */public class OrdetDrawLinearLayout extends LinearLayout {    public OrdetDrawLinearLayout(Context context) {        this(context, null);    }    public OrdetDrawLinearLayout(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public OrdetDrawLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        setChildrenDrawingOrderEnabled(true);    }    <span style="font-family:KaiTi_GB2312;">//改变其Child组件的绘制顺序</span>    @Override    protected int getChildDrawingOrder(int childCount, int i) {        switch (i) {            case 1:                return 0;            case 0:                return 1;        }        return super.getChildDrawingOrder(childCount, i);    }}




自定义属性:在main/ res/ values 文件夹下,建attrs文件,里面写下面代码

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="SlidingMenr">        <attr name="left_off_width" format="integer"/>    </declare-styleable></resources>


1 0