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