Android realization analysis Tenth of SlidingMenu sliding menu

Android realization analysis Tenth of SlidingMenu sliding menu

SlidingMenu sliding menu is a relatively new configuration settings interface or the interface effect, slide left or right slide interface effect is provided in the main interface, you can easily perform various operations. A lot of good applications using this interface programs like facebook, all networks, everynote, Google +, Netease news, know almost daily, the proper way cloud notes, etc.

 

Sliding menu implementation principles:
the layout of an Activity in need of two parts, one is the menu (menu) layout is a layout of content (content) of. Two transversely aligned layout, the layout of the menu on the left, the right content layout. Initialization of the offset to the left menu layout that can be completely hidden, so the content layout will be completely displayed in an Activity. Then by listening to the finger sliding events, to change the menu layout left offset distance, thereby controlling the display and hide the menu layout.

 

 

Two: the implementation process: opening the button to expand the sliding menu, click again to close the sliding menu.

1, the introduction of custom components SlideMenu

SlideMenu.java

package   com.example.walkerlogin1.view;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;

public class SlideMenu extends ViewGroup {
	public static final int SCREEN_MENU = 0;
	public static final int SCREEN_MAIN = 1;
	private static final int SCREEN_INVALID = -1;
	
	private int mCurrentScreen;
	private int mNextScreen = SCREEN_INVALID;

	private Scroller mScroller;
	private VelocityTracker mVelocityTracker;
	private int mTouchSlop;
	
	private float mLastMotionX;
	private float mLastMotionY;

	private final static int TOUCH_STATE_REST = 0;
	private final static int TOUCH_STATE_SCROLLING = 1;
	private static final int SNAP_VELOCITY = 1000;

	public int mTouchState = TOUCH_STATE_REST;
	private boolean mLocked;
	private boolean mAllowLongPress;

	public SlideMenu(Context context) {
		this(context, null, 0);
	}

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

	public SlideMenu(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		mScroller = new Scroller(getContext());
		mCurrentScreen = SCREEN_MAIN;
		mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		measureViews(widthMeasureSpec, heightMeasureSpec);
	}

	public void measureViews(int widthMeasureSpec, int heightMeasureSpec) {
		View menuView = getChildAt(0);
		menuView.measure(menuView.getLayoutParams().width + menuView.getLeft()
				+ menuView.getRight(), heightMeasureSpec);

		View contentView = getChildAt(1);
		contentView.measure(widthMeasureSpec, heightMeasureSpec);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		int childCount = getChildCount();
		if (childCount != 2) {
			throw new IllegalStateException(
					"The childCount of SlidingMenu must be 2");
		}

		View menuView = getChildAt(0);
		final int width = menuView.getMeasuredWidth();
		menuView.layout(-width, 0, 0, menuView.getMeasuredHeight());

		View contentView = getChildAt(1);
		contentView.layout(0, 0, contentView.getMeasuredWidth(),
				contentView.getMeasuredHeight());
	}
	
	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		View child;
		for (int i = 0; i < getChildCount(); i++) {
			child = getChildAt(i);
			child.setFocusable(true);
			child.setClickable(true);
		}
	}
	
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		if (mLocked) {
			return true;
		}

		final int action = ev.getAction();
		if ((action == MotionEvent.ACTION_MOVE)
				&& (mTouchState != TOUCH_STATE_REST)) {
			return true;
		}

		final float x = ev.getX();
		final float y = ev.getY();

		switch (action) {
		case MotionEvent.ACTION_MOVE:

			final int xDiff = (int) Math.abs(x - mLastMotionX);
			final int yDiff = (int) Math.abs(y - mLastMotionY);

			final int touchSlop = mTouchSlop;
			boolean xMoved = xDiff > touchSlop;
			boolean yMoved = yDiff > touchSlop;

			if (xMoved || yMoved) {

				if (xMoved) {
					// Scroll if the user moved far enough along the X axis
					mTouchState = TOUCH_STATE_SCROLLING;
					enableChildrenCache();
				}
				// Either way, cancel any pending longpress
				if (mAllowLongPress) {
					mAllowLongPress = false;
					// Try canceling the long press. It could also have been
					// scheduled
					// by a distant descendant, so use the mAllowLongPress flag
					// to block
					// everything
					final View currentScreen = getChildAt(mCurrentScreen);
					currentScreen.cancelLongPress();
				}
			}
			break;

		case MotionEvent.ACTION_DOWN:
			// Remember location of down touch
			mLastMotionX = x;
			mLastMotionY = y;
			mAllowLongPress = true;

			mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST
					: TOUCH_STATE_SCROLLING;

			break;

		case MotionEvent.ACTION_CANCEL:
		case MotionEvent.ACTION_UP:
			// Release the drag
			clearChildrenCache();
			mTouchState = TOUCH_STATE_REST;
			mAllowLongPress = false;
			break;
		}

		/*
		 * The only time we want to intercept motion events is if we are in the
		 * drag mode.
		 */
		return mTouchState != TOUCH_STATE_REST;
	}
	
	void enableChildrenCache() {
		final int count = getChildCount();
		for (int i = 0; i < count; i++) {
			final View layout = (View) getChildAt(i);
			layout.setDrawingCacheEnabled(true);
		}
	}

	void clearChildrenCache() {
		final int count = getChildCount();
		for (int i = 0; i < count; i++) {
			final View layout = (View) getChildAt(i);
			layout.setDrawingCacheEnabled(false);
		}
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		if (mLocked) {
			return true;
		}

		if (mVelocityTracker == null) {
			mVelocityTracker = VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(ev);

		final int action = ev.getAction();
		final float x = ev.getX();

		switch (action) {
		case MotionEvent.ACTION_DOWN:
			/*
			 * If being flinged and user touches, stop the fling. isFinished
			 * will be false if being flinged.
			 */
			if (!mScroller.isFinished()) {
				mScroller.abortAnimation();
			}

			// Remember where the motion event started
			mLastMotionX = x;
			break;
		case MotionEvent.ACTION_MOVE:
			if (mTouchState == TOUCH_STATE_SCROLLING) {
				// Scroll to follow the motion event
				final int deltaX = (int) (mLastMotionX - x);
				mLastMotionX = x;

				if (deltaX < 0) {
					if (deltaX + getScrollX() >= -getChildAt(0).getWidth()) {
						scrollBy(deltaX, 0);
					}

				} else if (deltaX > 0) {
					final int availableToScroll = getChildAt(
							getChildCount() - 1).getRight()
							- getScrollX() - getWidth();

					if (availableToScroll > 0) {
						scrollBy(Math.min(availableToScroll, deltaX), 0);
					}
				}
			}
			break;
		case MotionEvent.ACTION_UP:
			if (mTouchState == TOUCH_STATE_SCROLLING) {
				final VelocityTracker velocityTracker = mVelocityTracker;
				velocityTracker.computeCurrentVelocity(1000);
				int velocityX = (int) velocityTracker.getXVelocity();

				if (velocityX > SNAP_VELOCITY && mCurrentScreen == SCREEN_MAIN) {
					// Fling hard enough to move left
					snapToScreen(SCREEN_MENU);
				} else if (velocityX < -SNAP_VELOCITY
						&& mCurrentScreen == SCREEN_MENU) {
					// Fling hard enough to move right
					snapToScreen(SCREEN_MAIN);
				} else {
					snapToDestination();
				}

				if (mVelocityTracker != null) {
					mVelocityTracker.recycle();
					mVelocityTracker = null;
				}
			}
			mTouchState = TOUCH_STATE_REST;
			break;
		case MotionEvent.ACTION_CANCEL:
			mTouchState = TOUCH_STATE_REST;
		}

		return true;
	}
	
	@Override
	public void computeScroll() {
		if (mScroller.computeScrollOffset()) {
			scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
		} else if (mNextScreen != SCREEN_INVALID) {
			mCurrentScreen = Math.max(0,
					Math.min(mNextScreen, getChildCount() - 1));
			mNextScreen = SCREEN_INVALID;
			clearChildrenCache();
		}
	}

	@Override
	public void scrollTo(int x, int y) {
		super.scrollTo(x, y);
		postInvalidate();
	}

	@Override
	protected void dispatchDraw(Canvas canvas) {
		final int scrollX = getScrollX();
		super.dispatchDraw(canvas);
		canvas.translate(scrollX, 0);
	}

	@Override
	public boolean dispatchUnhandledMove(View focused, int direction) {
		if (direction == View.FOCUS_LEFT) {
			if (getCurrentScreen() > 0) {
				snapToScreen(getCurrentScreen() - 1);
				return true;
			}
		} else if (direction == View.FOCUS_RIGHT) {
			if (getCurrentScreen() < getChildCount() - 1) {
				snapToScreen(getCurrentScreen() + 1);
				return true;
			}
		}
		return super.dispatchUnhandledMove(focused, direction);
	}
	
	protected void snapToScreen(int whichScreen) {

		enableChildrenCache();

		whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
		boolean changingScreens = whichScreen != mCurrentScreen;

		mNextScreen = whichScreen;

		View focusedChild = getFocusedChild();
		if (focusedChild != null && changingScreens
				&& focusedChild == getChildAt(mCurrentScreen)) {
			focusedChild.clearFocus();
		}

		final int newX = (whichScreen - 1) * getChildAt(0).getWidth();
		final int delta = newX - getScrollX();
		mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2);
		invalidate();
	}

	protected void snapToDestination() {
		if (getScrollX() == 0) {
			return;
		}
		final int screenWidth = getChildAt(0).getWidth();
		final int whichScreen = (screenWidth + getScrollX() + (screenWidth / 2))
				/ screenWidth;
		snapToScreen(whichScreen);
	}
	
	public int getCurrentScreen() {
		return mCurrentScreen;
	}
	
	public boolean isMainScreenShowing() {
		return mCurrentScreen == SCREEN_MAIN;
	}
	
	public void openMenu() {
		mCurrentScreen = SCREEN_MENU;
		snapToScreen(mCurrentScreen);
	}
	
	public void closeMenu() {
		mCurrentScreen = SCREEN_MAIN;
		snapToScreen(mCurrentScreen);
	}
	
	public void unlock() {
		mLocked = false;
	}

	public void lock() {
		mLocked = true;
	}
	
}

In the following vlues strings.xml, add the following codes

<?xml version="1.0" encoding="utf-8"?>
<resources>

    
    <item>用户登录</item>
    <item>运动测试</item>
    <item>个人信息</item>
    <item>行程记录</item>
    <item>天气查询</item>
    <item>健康栏目</item>
    <item>软件设置</item>
   
</string-array>
</resources>

Item.java

package com.example.walkerlogin1.view;

public class Item {
	private String name;
	private int imageId;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getImageId() {
		return imageId;
	}
	public void setImageId(int imageId) {
		this.imageId = imageId;
	}
	public Item(String name, int imageId) {
		super();
		this.name = name;
		this.imageId = imageId;
	}
	
}

Set up a data source

ItemAdapter.java

package com.example.walkerlogin1.view;

import java.util.List;

import com.example.walkerlogin1.R;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class ItemAdapter extends ArrayAdapter<Item> {

public ItemAdapter(Context context, int textViewResourceId,
			List<Item> objects) {
		super(context,  textViewResourceId, objects);
		// TODO Auto-generated constructor stub
		resourceId=textViewResourceId;
	}


	private int resourceId;

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		Item item = getItem(position);
		View view;
		ViewHolder viewHolder;
		if (convertView == null) {
			view = LayoutInflater.from(getContext()).inflate(resourceId, null);

			viewHolder = new ViewHolder();
			viewHolder.ivIcon = (ImageView) view.findViewById(R.id.ivIcon);
			viewHolder.tvIntroduction = (TextView) view.findViewById(R.id.tvIntroduction);
			view.setTag(viewHolder);
		} else {
			view = convertView;
			viewHolder = (ViewHolder) view.getTag();
		}
		viewHolder.ivIcon.setImageResource(item.getImageId());
		viewHolder.tvIntroduction.setText(item.getName());
		return view;
	}
	
	class ViewHolder {
		
		ImageView ivIcon;
		
		TextView tvIntroduction;
		
	}

}

The main interface MainActivity2.java
 

package com.example.walkerlogin1;

import java.util.ArrayList;
import java.util.List;

import com.example.walkerlogin1.view.Item;
import com.example.walkerlogin1.view.ItemAdapter;
import com.example.walkerlogin1.view.SlideMenu;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;



public class MainActivity2 extends Activity {
	private SlideMenu slideMenu;
	private ImageView ivSwitchSlideMenu;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main2);
		initMenuList();
		slideMenu=(SlideMenu) findViewById(R.id.slideMenu);
		ivSwitchSlideMenu=(ImageView) findViewById(R.id.switch_slidemenu);
		ivSwitchSlideMenu.setOnClickListener(new OnClickListener() {
		public void onClick(View view) {
		if(slideMenu.isMainScreenShowing()){
		slideMenu.openMenu();
		}else{
		slideMenu.closeMenu();
		}
		}
		});
	}
	private void initMenuList() {
		int[] icons = { R.drawable.icons_menu_login,
		R.drawable.icons_menu_sport, R.drawable.icons_menu_inform,
		R.drawable.icons_menu_history, R.drawable.icons_menu_weather,
		R.drawable.icons_menu_health, R.drawable.icons_menu_setting };
		final String[] introductons = getResources().getStringArray(R.array.menulist);
		List<Item> items=new ArrayList<Item>();
		for(int i=0;i<icons.length;i++){
		   items.add(new Item(introductons[i],icons[i]));
		}
		ListView lvMenuList=(ListView) findViewById(R.id.lvMenuList);
		ItemAdapter itemAdapter=new ItemAdapter(this, R.layout.menulist_item, items);
		lvMenuList.setAdapter(itemAdapter);
		lvMenuList.setOnItemClickListener(new OnItemClickListener() {
		public void onItemClick(AdapterView<?> adapterView, View view, int position,
		long id) {
		//Toast.makeText(MainActivity2.this," 你点击了"+introductons[position],
		//Toast.LENGTH_LONG).show();
			Intent  intent=new Intent();
		switch (position) {
		  case 0:  //这里可以进行listview的点击跳转
			Toast.makeText(MainActivity2.this," 你点击了"+introductons[position],
					Toast.LENGTH_LONG).show();
			intent.setClass(getApplicationContext(), MainActivity.class);
			startActivity(intent);
			break;

		    default:
			break;
		}
		}
		});
}
}

UI layout activity_main.xml
 

<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" >

    <com.example.walkerlogin1.view.SlideMenu
        android:id="@+id/slideMenu"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <!-- 侧滑菜单 -->

        <include layout="@layout/leftmenu" />
        <!-- 主界面 -->

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <include layout="@layout/main_layout_titlebar" />

            <include layout="@layout/main_layout_content" />
        </LinearLayout>
    </com.example.walkerlogin1.view.SlideMenu>

</RelativeLayout>

leftmenu.xml
 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.example.walkerlogin1"
    android:layout_width="200dp"
    android:layout_height="match_parent"
    android:background="@drawable/leftmenu_bg" >

    <com.makeramen.roundedimageview.RoundedImageView
        android:id="@+id/rivUserPhoto"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:src="@drawable/test_photo"
        app:riv_oval="true" />

    <TextView
        android:id="@+id/tvMotto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/rivUserPhoto"
        android:layout_marginBottom="24dp"
        android:layout_marginLeft="5dp"
        android:layout_toRightOf="@+id/rivUserPhoto"
        android:text="奔跑无止境"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="@color/white" />

    <ListView
        android:id="@+id/lvMenuList"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_below="@id/tvMotto"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:divider="@color/whitesmoke"
        android:dividerHeight="1dp"
        android:listSelector="#00000000" >
    </ListView>

</RelativeLayout>

main_layout_titlebar.xml
 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="45.0dip"
    android:background="@drawable/titlebar_bg"
    android:gravity="center_vertical" >

    <ImageView
        android:id="@+id/switch_slidemenu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="3.0dip"
        android:gravity="center"       
        android:src="@drawable/switch_silidemenu" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:text="Walker"
        android:textColor="@color/white"
        android:textSize="22sp" />

    <ImageView
        android:id="@+id/switch_map"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="15.0dip"
        android:src="@drawable/switch_map" />

</RelativeLayout>


main_layout_content.xml
 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/welcome_bg" >

    <TextView
        android:id="@+id/tvCity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:text="滨州市"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/tvTemperature"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/tvCity"
        android:layout_below="@+id/tvCity"
        android:layout_marginRight="26dp"
        android:layout_marginTop="40dp"
        android:text="temperature"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:id="@+id/tvDay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tvTemperature"
        android:layout_below="@+id/tvTemperature"
        android:layout_marginTop="20dp"
        android:text="星期日"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:id="@+id/tvWeather"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tvDay"
        android:layout_below="@+id/tvDay"
        android:layout_marginTop="24dp"
        android:text="晴"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/tvTemperature"
        android:layout_marginLeft="24dp"
        android:layout_toRightOf="@+id/tvTemperature"
        android:background="#00000000"
        android:src="@drawable/monkey" />

</RelativeLayout>

The final layout

Click the button to the left or right to slide;

Published 269 original articles · won praise 2 · Views 6935

Guess you like

Origin blog.csdn.net/zhupengqq1/article/details/104260488