大家对于sliding_menu一定不会陌生,左右拖拽来节约空间同时效果也不错,先上个图
我们的两个button对应不同的两个activity,但要求是切换的内容都要在右侧可见,而不是开启一个新的页面
我的实现是通过ActivityGroup+sliding_menu来实现的。直接上代码
A:主页面布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <!-- 主布局 --> <RelativeLayout android:id="@+id/mainLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:id="@+id/titlebar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ffffff" android:padding="5dip"> <ImageView android:id="@+id/ivMore" android:src="@drawable/nav_more_normal" android:contentDescription="@string/img_desc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_alignParentLeft="true" android:layout_marginLeft="10dip"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/title" android:textSize="20sp" android:textColor="#000000"/> <ImageView android:id="@+id/ivSettings" android:src="@drawable/nav_setting_normal" android:contentDescription="@string/img_desc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:layout_marginRight="10dip"/> </RelativeLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/MyContent" android:orientation="vertical" android:layout_below="@id/titlebar" android:background="@drawable/picture" ></LinearLayout> </RelativeLayout> <!-- 左侧菜单导航 --> <RelativeLayout android:id="@+id/leftLayout" android:layout_width="140dip" android:layout_height="match_parent" android:background="#000000"> <RelativeLayout android:id="@+id/leftTitlebar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/grey21" android:padding="5dip"> <TextView android:layout_marginLeft="5dip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:text="@string/leftNav" android:textSize="20sp" android:textColor="#ffffff"/> </RelativeLayout> <LinearLayout android:id="@+id/layoutSlideMenu" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/leftTitlebar"> <Button android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="act1" /> <Button android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="act2" /> </LinearLayout> </RelativeLayout> </RelativeLayout>B:子页面布局【根据需求自己替换
<?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"> <TextView android:id="@+id/tv_item" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dp" android:text="button1" android:textSize="20sp" /> </RelativeLayout>
package com.chris.lr.slidemenu; import android.os.AsyncTask; import android.os.Bundle; import android.util.DisplayMetrics; import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.Window; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.RelativeLayout.LayoutParams; import android.app.Activity; import android.app.ActivityGroup; import android.content.Intent; public class MainActivity extends ActivityGroup implements OnGestureListener, OnTouchListener,OnClickListener { private static final String TAG = "ChrisSlideMenu"; private RelativeLayout mainLayout; private RelativeLayout leftLayout; private LinearLayout layoutSlideMenu; LinearLayout bodyLayout; private ImageView ivMore; private ImageView ivSettings; private GestureDetector mGestureDetector; private static final int SPEED = 30; private boolean bIsScrolling = false; private int iLimited = 0; private int mScroll = 0; private View mClickedView = null; Button button1; Button button2; private static int TABSWITCHSTATE = 1; private static final int TABSWITCHBASEINFO = 1; private static final int TABSWITCHNEWPUSH = 2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initView(); initTab(); } private void initView(){ mainLayout = (RelativeLayout) findViewById(R.id.mainLayout); leftLayout = (RelativeLayout) findViewById(R.id.leftLayout); button1 = (Button) findViewById( R.id.btn1 ); button2 = (Button) findViewById( R.id.btn2 ); bodyLayout = (LinearLayout) findViewById( R.id.MyContent ); button1.setOnClickListener( this ); button2.setOnClickListener( this ); mainLayout.setOnTouchListener(this); leftLayout.setOnTouchListener(this); layoutSlideMenu = (LinearLayout) findViewById(R.id.layoutSlideMenu); ivMore = (ImageView) findViewById(R.id.ivMore); ivSettings = (ImageView) findViewById(R.id.ivSettings); ivMore.setOnTouchListener(this); ivSettings.setOnTouchListener(this); mGestureDetector = new GestureDetector(this); mGestureDetector.setIsLongpressEnabled(false); resizeLayout(); } Intent intentBase ; Intent intentList; private void initTab(){ intentBase = new Intent(MainActivity.this, A1.class) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intentList = new Intent(MainActivity.this, A2.class) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); bodyLayout.addView( getLocalActivityManager().startActivity( "a1", intentBase ).getDecorView() ); } /* * 使用leftMargin及rightMargin防止layout被挤压变形 * Math.abs(leftMargin - rightMargin) = layout.width */ private void resizeLayout(){ DisplayMetrics dm = getResources().getDisplayMetrics(); // 固定 main layout, 防止被左、右挤压变形 RelativeLayout.LayoutParams lp = (LayoutParams) mainLayout.getLayoutParams(); lp.width = dm.widthPixels; mainLayout.setLayoutParams(lp); // 将左layout调整至main layout左边 lp = (LayoutParams) leftLayout.getLayoutParams(); lp.leftMargin = -lp.width; leftLayout.setLayoutParams(lp); Log.d(TAG, "left l.margin = " + lp.leftMargin); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0){ RelativeLayout.LayoutParams lp = (LayoutParams) mainLayout.getLayoutParams(); if(lp.leftMargin != 0){ if(lp.leftMargin > 0){ new SlideMenu().execute(leftLayout.getLayoutParams().width, -SPEED); } return true; } } return super.onKeyDown(keyCode, event); } private void rollLayout(int margin){ RelativeLayout.LayoutParams lp = (LayoutParams) mainLayout.getLayoutParams(); lp.leftMargin += margin; lp.rightMargin -= margin; mainLayout.setLayoutParams(lp); lp = (LayoutParams) leftLayout.getLayoutParams(); lp.leftMargin += margin; leftLayout.setLayoutParams(lp); } private void onScroll(float distanceX){ bIsScrolling = true; mScroll += distanceX; // 向左为正 Log.d(TAG, "mScroll = " + mScroll + ", distanceX = " + distanceX); RelativeLayout.LayoutParams lp = (LayoutParams) mainLayout.getLayoutParams(); RelativeLayout.LayoutParams lpLeft = (LayoutParams) leftLayout.getLayoutParams(); Log.d(TAG, "lp.leftMargin = " + lp.leftMargin); int distance = 0; if(mScroll > 0){ // 向左移动 if(lp.leftMargin <= 0){ // 打开右导航菜单 if(iLimited > 0){ return; } }else if(lp.leftMargin > 0){ // 关闭左导航菜单 distance = lp.leftMargin; } if(mScroll >= distance){ mScroll = distance; } }else if(mScroll < 0){ // 向右移动 if(lp.leftMargin >= 0){ // 打开左导航菜单 if(iLimited < 0){ return; } distance = lpLeft.width - Math.abs(lp.leftMargin); }else if(lp.leftMargin < 0){ // 关闭右导航菜单 distance = Math.abs(lp.leftMargin); } if(mScroll <= -distance){ mScroll = -distance; } } Log.d(TAG, "mScroll = " + mScroll); if(mScroll != 0){ rollLayout(-mScroll); } } private void onRelease(){ RelativeLayout.LayoutParams lp = (LayoutParams) mainLayout.getLayoutParams(); if(lp.leftMargin < 0){}else if(lp.leftMargin > 0){ /* * 右移大于左导航宽度一半,则自动展开,否则自动缩回去 */ if(Math.abs(lp.leftMargin) > leftLayout.getLayoutParams().width/2){ new SlideMenu().execute(leftLayout.getLayoutParams().width - Math.abs(lp.leftMargin), SPEED); }else{ new SlideMenu().execute(Math.abs(lp.leftMargin), -SPEED); } } } ////////////////////////////// onTouch /////////////////////////////// @Override public boolean onTouch(View v, MotionEvent event) { mClickedView = v; if(MotionEvent.ACTION_UP == event.getAction() && bIsScrolling){ onRelease(); } return mGestureDetector.onTouchEvent(event); } /////////////////// GestureDetector Override Begin /////////////////// @Override public boolean onDown(MotionEvent e) { bIsScrolling = false; mScroll = 0; iLimited = 0; RelativeLayout.LayoutParams lp = (LayoutParams) mainLayout.getLayoutParams(); if(lp.leftMargin > 0){ iLimited = 1; }else if(lp.leftMargin < 0){ iLimited = -1; } return true; } @Override public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) { return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { onScroll(distanceX); return false; } @Override public void onShowPress(MotionEvent arg0) { } @Override public boolean onSingleTapUp(MotionEvent e) { /* * 正常情况下,mainLayout的leftMargin为0, * 当左/右菜单为打开中,此时就不为0,需要判断 */ if(mClickedView != null){ RelativeLayout.LayoutParams lp = (LayoutParams) mainLayout.getLayoutParams(); if(mClickedView == ivMore){ Log.d(TAG, "[onSingleTapUp] ivMore clicked! leftMargin = " + lp.leftMargin); if(lp.leftMargin == 0){ new SlideMenu().execute(leftLayout.getLayoutParams().width, SPEED); }else{ new SlideMenu().execute(leftLayout.getLayoutParams().width, -SPEED); } }else if(mClickedView == mainLayout){ Log.d(TAG, "[onSingleTapUp] mainLayout clicked!"); } } return true; } /////////////////// GestureDetector Override End /////////////////// /** * * @author cheng.yang * * 左、右菜单滑出 * * params[0]: 滑动距离 * params[1]: 滑动速度,带方向 */ public class SlideMenu extends AsyncTask<Integer, Integer, Void>{ @Override protected Void doInBackground(Integer... params) { if(params.length != 2){ Log.e(TAG, "error, params must have 2!"); } int times = params[0] / Math.abs(params[1]); if(params[0] % Math.abs(params[1]) != 0){ times ++; } for(int i = 0; i < times; i++){ this.publishProgress(params[0], params[1], i+1); } return null; } @Override protected void onProgressUpdate(Integer... values) { if(values.length != 3){ Log.e(TAG, "error, values must have 3!"); } int distance = Math.abs(values[1]) * values[2]; int delta = values[0] - distance; int leftMargin = 0; if(values[1] < 0){ // 左移 leftMargin = (delta > 0 ? values[1] : -(Math.abs(values[1]) - Math.abs(delta))); }else{ leftMargin = (delta > 0 ? values[1] : (Math.abs(values[1]) - Math.abs(delta))); } rollLayout(leftMargin); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn1: if(TABSWITCHSTATE == TABSWITCHBASEINFO){ return; } bodyLayout.removeAllViews(); bodyLayout.addView( getLocalActivityManager().startActivity( "a1", intentBase ).getDecorView() ); TABSWITCHSTATE = TABSWITCHBASEINFO; break; case R.id.btn2: if(TABSWITCHSTATE == TABSWITCHNEWPUSH){ return; } bodyLayout.removeAllViews(); bodyLayout.addView( getLocalActivityManager().startActivity( "a2", intentList ).getDecorView() ); TABSWITCHSTATE = TABSWITCHNEWPUSH; break; default: break; } } }