有一段時間沒有寫部落格了,最近比較忙,沒什麼時間寫,剛好今天有點時間,
我就分享下,側滑菜單的實作原理,一般android側滑的實作原理和步驟如下:(源碼下載下傳在下面最後給出哈)
1.使用ViewGroup 放2個view,一個是menu菜單,一個是content内容
2.監聽onTouchEvent事件
處理ACTION_MOVE中的leftMargin位置,進而改變menu菜單的滑動位置
當ACTION_UP時,根據顯示菜單的寬度,決定将其顯示或隐藏動畫效果:
(1)使用Scroller這個輔助類實作動畫效果
(2)單起一個Thread(或Task)來改變leftMargin的大小來實作動畫效果
上面這種方法,當監聽ACTION_MOVE時候,當菜單裡有listview等view到時候容易引起手勢監聽的沖突。
為了避免這種問題,我們采用新的方法來做側滑。主要是做以下兩個處理:
1.不繼承ViewGroup,而是繼承HorizontalScrollView,這樣做的好處是HorizontalScrollView已經幫我們做了相關的監聽滑動手勢沖突的處理,我們不用操心和處理這些問題。
2.計算Menu菜單的大小,并顯示與隐藏menu
3.顯示和隐藏menu的動畫效果,使用nineoldandroids這個android屬性動畫開源庫。
側滑菜單的效果截圖如下:
上面介紹了原理和效果圖,下面來看看側滑菜單類的實作:
1.布局檔案的實作:
(1)左側菜單布局實作:
<?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="#00000000" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerInParent="true"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/menu1"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:textColor="#ffffff"
android:textSize="25sp"
android:text="第一個item1" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/menu2"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:textColor="#ffffff"
android:textSize="25sp"
android:text="第二個item2" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/menu3"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:textColor="#ffffff"
android:textSize="25sp"
android:text="第三個item3" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/menu4"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:textColor="#ffffff"
android:textSize="25sp"
android:text="第四個item4" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/menu5"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:textColor="#ffffff"
android:textSize="25sp"
android:text="第五個item5" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
(2)總布局實作:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.czm.xcslidemenu.view.XCSlideMenu
android:id="@+id/slideMenu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/img_frame_background"
android:scrollbars="none" >
<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/qihu" >
<TextView
android:id="@+id/btnSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/btn_bg"
android:padding="5dp"
android:textSize="16sp"
android:textColor="#FFF"
android:layout_margin="10dp"
android:text="切換菜單" />
</LinearLayout>
</LinearLayout>
</com.czm.xcslidemenu.view.XCSlideMenu>
</RelativeLayout>
2.側滑菜單類的實作:
package com.czm.xcslidemenu.view;
import com.nineoldandroids.view.ViewHelper;
import android.animation.FloatEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
/**
* 自定義側滑菜單View
* @author caizhiming
*
*/
public class XCSlideMenu extends HorizontalScrollView{
private LinearLayout mWapper;
private ViewGroup mMenu;
private ViewGroup mContent;
private int mScreenWidth;
private int mMenuRightPadding;
private int mMenuWidth = 0;
private boolean once = false;
//Menu是否處于顯示狀态
private boolean isSlideOut;
public static final int RIGHT_PADDING = 100;
public XCSlideMenu(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
mScreenWidth = metrics.widthPixels;
//将dp轉化為px
mMenuRightPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, XCSlideMenu.RIGHT_PADDING, context.getResources().getDisplayMetrics());
}
/**
* 設定子View的寬和高
* 設定自己的寬和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
if(!once){
mWapper = (LinearLayout) getChildAt(0);
mMenu = (ViewGroup) mWapper.getChildAt(0);
mContent = (ViewGroup) mWapper.getChildAt(1);
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) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
if(changed){
this.scrollTo(mMenuWidth, 0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
//隐藏在左邊寬度
int scrollX = getScrollX();
if(scrollX >= mMenuWidth /2){
//Menu 左滑隐藏起來
this.smoothScrollTo(mMenuWidth, 0);
isSlideOut = false;
}else{
//Menu 右滑 顯示出來
this.smoothScrollTo(0, 0);
isSlideOut = true;
}
return true;
}
return super.onTouchEvent(ev);
}
/**
* 向右滑出菜單顯示出來
*/
public void slideOutMenu(){
if(!isSlideOut){
this.smoothScrollTo(0, 0);
isSlideOut = true;
}else{
return;
}
}
/**
* 向左滑出菜單隐藏起來
*/
public void slideInMenu(){
if(isSlideOut){
this.smoothScrollTo(mMenuWidth, 0);
isSlideOut = false;
}else{
return;
}
}
/**
* 切換菜單向右滑出顯示或向左滑出隐藏的狀态
*/
public void switchMenu(){
if(isSlideOut){
slideInMenu();
}else{
slideOutMenu();
}
}
/**
* 滾動發生時
*/
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
// TODO Auto-generated method stub
super.onScrollChanged(l, t, oldl, oldt);
//實作抽屜式滑動
float scale = l * 1.0f /mMenuWidth ;//1 ~ 0
float menuScale = 1.0f - scale * 0.3f;
float menuAlpha = 0.0f + 1.0f * (1 - scale);
float contentScale = 0.8f + 0.2f * scale;
//調用屬性動畫,設定TranslationX
ViewHelper.setTranslationX(mMenu, mMenuWidth*scale*0.8f);
//左側菜單的縮放
ViewHelper.setScaleX(mMenu, menuScale);
ViewHelper.setScaleY(mMenu, menuScale);
//左側菜單的透明度縮放
ViewHelper.setAlpha(mMenu, menuAlpha);
//右側内容的縮放
ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent, mContent.getHeight() / 2);
ViewHelper.setScaleY(mContent, contentScale);
ViewHelper.setScaleX(mContent, contentScale);
}
}
最後,如何使用該側滑菜單類呢?很簡單,請看下面執行個體代碼:
package com.czm.xcslidemenu;
import com.czm.xcslidemenu.view.XCSlideMenu;
import android.app.Activity;
import android.app.ActionBar;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.os.Build;
public class MainActivity extends Activity {
private XCSlideMenu xcSlideMenu;
private TextView btnSwitch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
xcSlideMenu = (XCSlideMenu) findViewById(R.id.slideMenu);
btnSwitch = (TextView)findViewById(R.id.btnSwitch);
btnSwitch.setClickable(true);
btnSwitch.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
xcSlideMenu.switchMenu();
}
});
}
}
最後給出源碼的下載下傳:http://download.csdn.net/detail/jczmdeveloper/8286307
真題園網:http://www.zhentiyuan.com
轉載于:https://www.cnblogs.com/JczmDeveloper/p/4178227.html