仿QQ侧滑菜单效果

这里写图片描述

1、继承HorizontalScrollerView(水平滚动条),好处:无需判断高度只需考虑水平宽度,可以省去MOVE冲突的处理。
2、菜单布局文件left_menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/img_frame_background"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

          <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableLeft="@drawable/img_1"
            android:gravity="center"
            android:textColor="#ffffff"
            android:textSize="20sp"
            android:text="第一个文本" />
          <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableLeft="@drawable/img_2"
            android:gravity="center"
             android:textColor="#ffffff"
            android:textSize="20sp"
            android:text="第二个文本" />

    </LinearLayout> 

</RelativeLayout>

mainActivity.xml文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:dan="http://schemas.android.com/apk/res/com.example.recycleview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.recycleview.view.SlidingMenu
        android:id="@+id/id_menu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        dan:rightPadding="100dp" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="horizontal" >

            <include layout="@layout/left_menu" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/qq" >

                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:onClick="toggleMenu"
                    android:text="切换菜单" />
            </LinearLayout>
        </LinearLayout>
    </com.example.recycleview.view.SlidingMenu>

</RelativeLayout>

3、自定义View:SlidingMenu.java,继承水平滚动控件类
1、首先实现其两个参数的构造方法
2、将自定义的HorizontalScrollView名字改成自定义的属性名 包名+类名
…………………………
>
3、自定义ViewGroup:
(1)、onMeasure:决定内部View(子View)的宽和高以及自己的宽和高
(2)、onLayout:决定子View放置的位置
(3)、onTouchEvent:判断用户的手指状态


public class SlidingMenu extends HorizontalScrollView {
    private LinearLayout mWapper;
    private ViewGroup mMenu;
    private ViewGroup mContent;
    private int mScreenWidth;
    private int mMenuRightPadding = 50;// menu与屏幕右侧的距离dp
    private int mMenuWidth;
    private boolean once;// onMeasure会调用多次,设置一个boolean值
    private boolean isOpen; //默认打开时为false
    float scale;
    /*
     * 没有使用自定义属性时,调用这个参数
     */
    public SlidingMenu(Context context, AttributeSet attrs) {
        this(context, attrs,0);

    }

    /*
     * 自定义ViewGroup 1、onMeasure 决定内部view的宽和高 2、onLayout 决定子view的放置的位置
     * 3、onTouchEvent 判断用户的手指状态
     */

    /*
     * 当使用了自定义属性时,会调用此构造方法
     */

    public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // 获取我们定义的属性
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
                R.styleable.SlidingMenu, defStyle, 0);
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr = a.getIndex(i);
            switch (attr) {
            case R.styleable.SlidingMenu_rightPadding:
                mMenuRightPadding = a.getDimensionPixelSize(attr,
                        (int) TypedValue.applyDimension(
                                TypedValue.COMPLEX_UNIT_DIP, 50, context
                                        .getResources().getDisplayMetrics()));// attr是新赋值,第二个是默认值
                break;

            }
        }

        a.recycle();// 释放掉
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);// 宽高被赋值了
        mScreenWidth = outMetrics.widthPixels;

    }

    public SlidingMenu(Context context) {
        this(context, null);
        // TODO Auto-generated constructor stub
    }

    // 设置子view的宽和高,设置自己的宽和高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (!once) {
            mWapper = (LinearLayout) getChildAt(0);
            mMenu = (ViewGroup) mWapper.getChildAt(0);// LinearLayout第一个元素
            mContent = (ViewGroup) mWapper.getChildAt(1);// LinearLayout第二个元素
            mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth
                    - mMenuRightPadding;
            mContent.getLayoutParams().width = mScreenWidth;
            once = true;
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    // 通过设置偏移量,将menu隐藏
    @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);// scrollTo是隐藏的方法,瞬间完成的动作

        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {// 默认自动能把隐藏的滑出来,所以关心Action_UP
        int action = ev.getAction();
        switch (action) {
        case MotionEvent.ACTION_UP:
            int scrollX = getScrollX();// scrollX隐藏在左边的宽度
            if (scrollX >= mMenuWidth / 2) {
                this.smoothScrollTo(mMenuWidth, 0);// smoothScrollTo是动画隐藏的方法
                isOpen=false;
            } else {
                this.smoothScrollTo(0, 0);//打开menu
                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 toggle(){
        if(isOpen){
            closeMenu();
        }else {
            openMenu();
        }

    }

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
 scale=l*1.0f/mMenuWidth;//1~0
//调用属性动画,设置TranslationX     mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth- mMenuRightPadding;
 float rightScale=0.7f+0.3f*scale;
 float leftScale=1.0f-scale*0.3f;
 float leftAlpha=0.6f+0.4f*(1-scale);
 ViewHelper.setTranslationX(mMenu, mMenuWidth*scale*0.8f);
 ViewHelper.setScaleX(mMenu, leftScale);
 ViewHelper.setScaleY(mMenu,leftScale );
 ViewHelper.setAlpha(mMenu, leftAlpha);
// mContent的缩放及焦点
 ViewHelper.setScaleX(mContent,rightScale);
 ViewHelper.setScaleY(mContent,rightScale);
ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent, mContent.getHeight()/2);

}


}

4、、用户自定义属性
至此,侧滑已经实现。接下来加入自定义属性,可以让用户去设置菜单离屏幕右边的边距。
(1)、在values文件夹中创建一个xml文件,叫做attr.xml
(2)注意:在xml文件中编写自定义属性时是没有代码提示功能的,因此要注意代码拼写
(3)接下来要在mainActivity.xml文件中命名空间进行声明:
xmlns:dan=”http://schemas.android.com/apk/res/com.example.recycleview”
注意:这里的格式是xmlns:自己编写,可以是任何名字=”http://schemas.android.com/apk/res/当前应用的包名,而不是View的包名”
(4)、接下来将自定义属性放到View中进行使用
Alan:rightPadding=”100dp”
(5)、在刚才未使用自定义属性时,调用自身的构造方法,定义之后,需要生成另外两个构造方法:将原来两个参数构造方法中的方法拷贝到三个参数的构造方法之中,然后将两个参数构造方法的第三个参数设置为0,将一个参数的构造方法(传入上下文对象方法)的第二个参数设置为null,即调用两个参数的构造方法。
(6)、获取我们定义的属性:在三个参数的构造方法中获取:通过TypedArray这个类获得自定义属性,这里需要注意的是TypedArray这个类用完之后需要进行释放(recycled)。

5、attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <attr name="rightPadding" format="dimension"></attr>

    <declare-styleable name="SlidingMenu">
        <attr name="rightPadding"></attr>
    </declare-styleable>

</resources>

6、下面是MainActivity的实现


public class MainActivity extends Activity  {
    private SlidingMenu mLeftMenu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        mLeftMenu=(SlidingMenu) findViewById(R.id.id_menu);


    }
    public void toggleMenu(View v){

        mLeftMenu.toggle();

    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值