仿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。

發佈了61 篇原創文章 · 獲贊 43 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章