安卓实现自定义侧滑菜单

来源:互联网 发布:淘宝如何查历史价格 编辑:程序博客网 时间:2024/05/16 06:34
/** * Created by on 2016/12/12. *      注意: HorizontalScrollView的内部布局只能是LinearLayout. *          1. onMeasure(): 决定内部view的宽和高,以及自己的宽和高 *          2. onLayout():决定子view放置的位置 *          3. onTouchEvent(): 决定内部view的移动效果 *      自定义属性: *          1. 创建attr.xml文件 *          2. 在布局文件里面设置并调用命名空间 xmlns:hyman="http://schemas.android.com/apk/res-auto" *             在xml布局文件里面使用属性 hyman:rightPadding="150dp" *          3. 在三个参数的构造函数里面获取自定义属性值 */
public class MyHorizontaScrollView  extends HorizontalScrollView{    private int mScreenWidth;//屏幕的宽度    private int menuRightPadding;//距离右边的距离    private LinearLayout mWapper;//第一层子View    private ViewGroup mMenu;//菜单view    private ViewGroup mContent;//内容的view    private boolean isOnce = false; //判断是否是第一次加载设置宽高    private int mMenuWidth;//menu菜单的宽度    private boolean isOpen = false;//菜单是否展示    public MyHorizontaScrollView(Context context){        this(context, null);    }    /**     * 未使用自定义属性的时候调用     * @param context     * @param attrs     */    public MyHorizontaScrollView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    /**     * 当使用了自定义属性的时候调用此方法     * 把dp转换成px: TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, context.getResources().getDisplayMetrics());     */    public MyHorizontaScrollView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        //获取我们定义的属性        TypedArray a = context.getTheme().obtainStyledAttributes(attrs , R.styleable.MyHorizontaScrollView,defStyleAttr , 0 );        int count = a.getIndexCount();        for (int i = 0 ; i<count ;i++){            int attr = a.getIndex(i);            switch (attr){                case R.styleable.MyHorizontaScrollView_rightPadding:                    menuRightPadding = a.getDimensionPixelSize(attr , (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics()));                    break;            }        }        a.recycle();//必须释放        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics dm = new DisplayMetrics();        wm.getDefaultDisplay().getMetrics(dm);        mScreenWidth = dm.widthPixels;    }    /**     * 设置内部view的宽和高,以及自己的宽和高     * @param widthMeasureSpec     * @param heightMeasureSpec     */    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        if(!isOnce){            mWapper = (LinearLayout) getChildAt(0);//获取第一层的LinearLayout            mMenu = (ViewGroup) mWapper.getChildAt(0);//获取菜单布局            mContent = (ViewGroup) mWapper.getChildAt(1);//获取内容布局            mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth - menuRightPadding;//设置菜单的宽度            mContent.getLayoutParams().width = mScreenWidth;//设置内容的宽度            isOnce = true;        }        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }    /**     * 通过设置偏移量,隐藏menu菜单     * @param changed     * @param l     * @param t     * @param r     * @param b     */    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        super.onLayout(changed, l, t, r, b);        if(changed){//不改变就不调用            this.scrollTo(mMenuWidth , 0); //移动(瞬间)        }    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        int action = ev.getAction();        switch (action){            case MotionEvent.ACTION_UP:                int scaleX = getScrollX();                if(scaleX >= mMenuWidth/2){                    this.smoothScrollTo(mMenuWidth , 0); //移动(有一个平滑的效果)                    isOpen = false;                }else {                    this.smoothScrollTo(0 , 0);                    isOpen = true;                }                return true;        }        return super.onTouchEvent(ev);    }    /**     * 手动打开菜单     */    public void openMenu(){        if(isOpen){            return;        }        this.smoothScrollTo(0 , 0);        isOpen = true;    }    /**     * 手动关闭菜单     */    public void closeMenu(){        if(!isOpen){            return;        }        this.smoothScrollTo(mMenuWidth , 0); //移动(有一个平滑的效果)        isOpen = false;    }    /**     * 切换菜单的状态     */    public void tabMenu(){        if(isOpen){            closeMenu();        }else {            openMenu();        }    }    /**     * 滚动的时候调用:     *          调用属性动画平移,实现抽屉式滑动的效果     * @param l = getScrollX()     */    private float currentWidth = mMenuWidth;    @Override    protected void onScrollChanged(int l, int t, int oldl, int oldt) {        super.onScrollChanged(l, t, oldl, oldt);        //调用属性动画,设置translationX。 android3.0引入的        double scale = l*1.0/mMenuWidth;//1-0        //ObjectAnimator extends ValueAnimator 参数:初始值、结束值        ObjectAnimator.ofFloat(mMenu, "translationX", currentWidth ,(float)(mMenuWidth*scale)).start();        currentWidth = (float)(mMenuWidth*scale);    }}




/** * 布局文件 */

<!-- HorizontaScrollView里面只能是LinearLayout --><com.fanghan.myapplication.views.MyHorizontaScrollView    android:id="@+id/myHorizontaScrollView"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:scrollbars="none"    hyman:rightPadding="150dp">        <LinearLayout            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:orientation="horizontal">            <include layout="@layout/activity_menu_left"/>            <LinearLayout                android:layout_width="match_parent"                android:layout_height="match_parent"                android:orientation="vertical"                android:background="@mipmap/switcher1">                <Button                    android:id="@+id/bt_tab"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:text="切换菜单状态"/>            </LinearLayout>        </LinearLayout></com.fanghan.myapplication.views.MyHorizontaScrollView>


0 0