仿QQ6.0主页侧滑效果

仿QQ6.0主页侧滑效果的实现,我们使用众所周知的我们常用的HorizontalScrollView来实现QQ的侧滑效果。首先我们来看一下运行效果图:

首先我们来打造一个侧滑菜单的menu类,让其继承自HorizontalScrollView。具体的实现我们来一起看代码SlidingMenu.java
源码下载我稍后在评论中给出,等了好久csdn不出地址没办法。。。

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;

import com.xyliwp.dayday.R;

/**
 * 侧滑菜单
 * Created by wenpengli on 2017/1/17.
 */
public class SlidingMenu extends HorizontalScrollView{

    private Context context;
    //菜单的内容
    private View mMenuView;
    private ViewGroup mContentView;
    //菜单的宽度
    private int mMenuWidth;
    //手势处理类 主要用来处理手势快速华东
    private GestureDetector mGestureDetector;
    //判断菜单是否打开
    private boolean mMenuIsOpen = false;
    private ImageView mShadowIV;

    public SlidingMenu(Context context) {
        this(context,null);
    }

    public SlidingMenu(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu);
        float rightPadding = typedArray.getDimension(R.styleable.SlidingMenu_rightPadding,dip2px(50));
        //计算菜单的宽度 = 屏幕的宽度-自定义右边留出的宽度
        mMenuWidth = (int)(getScreenWidth() - rightPadding);
        typedArray.recycle();
        //实例化手势处理类
        mGestureDetector = new GestureDetector(context,new GestrueListener());
        this.context = context;
    }

    /**
     * 把dip转化为像素
     * @param dip
     * @return
     */
    private float dip2px(int dip){
        return TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,dip,getResources().getDisplayMetrics()
        );
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        //获取根View也就是外层的LinearLayout
        ViewGroup container = (ViewGroup)this.getChildAt(0);
        int containerChaildcount = container.getChildCount();
        if (containerChaildcount > 2){
            //里面至于讯仿两个布局 一个是menu菜单 一个是content的内容
            throw new IllegalStateException("我们规定只允许仿两个VIew");
        }
        //获取菜单和内容的布局
        mMenuView = container.getChildAt(0);
        //给内容添加阴影效果
        mContentView = new FrameLayout(context);
        ViewGroup.LayoutParams contentParams = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
        );
        // 4.2.2.获取菜单和内容布局
        mMenuView = container.getChildAt(0);

        // 7.给内容添加阴影效果
        // 7.1 先new一个主内容布局用来放  阴影和LinearLayout原来的内容布局
        mContentView = new FrameLayout(context);
        contentParams = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

        // 7.2 获取原来的内容布局,并把原来的内容布局从LinearLayout中异常
        View oldContentView = container.getChildAt(1);
        container.removeView(oldContentView);

        // 7.3 把原来的内容View 和 阴影加到我们新创建的内容布局中
        mContentView.addView(oldContentView);
        // 7.3.1 创建阴影ImageView
        mShadowIV = new ImageView(context);
        mShadowIV.setBackgroundColor(Color.parseColor("#00000000"));
        mContentView.addView(mShadowIV);

        // 7.4 把包含阴影的新的内容View 添加到 LinearLayout中
        container.addView(mContentView);

        // 4.2.3.指定内容和菜单布局的宽度
        // 4.2.3.1 菜单的宽度 = 屏幕的宽度 - 自定义的右边留出的宽度
        mMenuView.getLayoutParams().width = mMenuWidth;
        // 4.2.3.2 内容的宽度 = 屏幕的宽度
        mContentView.getLayoutParams().width = getScreenWidth();
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        //处理手指快速华东
        if (mGestureDetector.onTouchEvent(ev)){
            return mGestureDetector.onTouchEvent(ev);
        }
        switch (ev.getAction()){
            case MotionEvent.ACTION_UP:
                //手指抬起来获取滚动的位置
                int currentScrollx = getScrollX();
                if (currentScrollx > mMenuWidth/2){
                    //关闭菜单
                    closeMenu();
                }else {
                    //打开菜单
                    openMenu();
                }
                return false;
        }
        return super.onTouchEvent(ev);
    }

    /**
     * 打开菜单
     */
    private void openMenu(){
        smoothScrollTo(0,0);
        mMenuIsOpen = true;
    }

    /**
     * 关闭菜单
     */
    private void closeMenu(){
        smoothScrollTo(mMenuWidth,0);
        mMenuIsOpen = false;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        //布局制定后 会从新拜访的子布局,当其摆放完毕后 让菜单滚动到不可见状态
        if (changed){
            scrollTo(mMenuWidth,0);
        }
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        //实现左边抽屉式动画效果
        mMenuView.setTranslationX(1*0.8f);
        float gradientValue = 1*1f / mMenuWidth;
        float shadowAlpha = 1-gradientValue;
        mShadowIV.setAlpha(shadowAlpha);
    }

    private class GestrueListener extends GestureDetector.SimpleOnGestureListener{
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            //房手指快速华东式 毁掉方法
            //如果菜单打开 并且是向左快速华东的  切换到菜单状态
            if (mMenuIsOpen){
                if (velocityX < -500){
                    toggleMenu();
                    return true;
                }
            }else {
                //如果是向右则 且菜菜单关闭切换回菜单状态\
                if (velocityY > 500){
                    toggleMenu();
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * 切换菜单状态
     */
    public void toggleMenu(){
        if (mMenuIsOpen){
            closeMenu();
        }else {
            openMenu();
        }
    }

    /**
     * 获取屏幕的宽度
     * @return
     */
    public int getScreenWidth(){
        Resources resources = this.getResources();
        DisplayMetrics dm = resources.getDisplayMetrics();
        return dm.widthPixels;
    }
}

在上代码中我们提到了styleable资源,如果不清楚styleable文件在哪设置,那么我们来简单的介绍一下styleable,它一般存放我们自定义控件的一些属性,该文件在values包下建立attrs.xml,在该xml下我们进行styleable的属性设置,xml的代码如下

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="SlidingMenu">
        <attr name="rightPadding" format="dimension"/>
    </declare-styleable>
</resources>

接下来就是主Activity的加载:

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.xyliwp.dayday.R;

/**
 * Created by wenpengli on 2017/1/17.
 */
public class SlidAcivity extends Activity{
    private SlidingMenu slidingMenu;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_slidingmenu);
        slidingMenu = (SlidingMenu)findViewById(R.id.slidingMenuActivity);
        Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                slidingMenu.toggleMenu();
                Toast.makeText(SlidAcivity.this,"菜单切换",Toast.LENGTH_SHORT).show();
            }
        });
    }
}

对于XML的代码分别如下:主XML

<?xml version="1.0" encoding="utf-8"?>
<com.xyliwp.dayday.sideslipmenu.SlidingMenu
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:id="@+id/slidingMenuActivity"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:rightPadding="62dp"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
        <include layout="@layout/layout_slid_menu"></include>
        <include layout="@layout/layout_slid_content"></include>
    </LinearLayout>
</com.xyliwp.dayday.sideslipmenu.SlidingMenu>

菜单XML:

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

</LinearLayout>

主页面的内容XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/bt1">
    <Button
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:id="@+id/button"
        android:text=""
        android:background="#00000000"/>
</LinearLayout>

就这样我们完成了很简单的仿QQ6.0的侧滑效果,然后你们可以发挥想象完成你们想完成的APP。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值