简单的android滑动侧边菜单sliderview

继承ViewGoup,重写onInterceptTouchEvent截拦触摸事件并按条件分发给子View。

package com.example.viewdemo;

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

public class SliderView extends ViewGroup {

	/**
	 * 速度边界
	 */
	private static final int VELOCITY_X_SPEED = 800;
	/**
	 * 最后一次触摸的x位置
	 */
	private float x;

	private Scroller scroller;
	/**
	 * 触摸事件是否已分发给子view
	 */
	private boolean dispatched;
	private boolean slided;
	private int startScrollLeftOffset;
	private VelocityTracker mVelocityTracker;

	public SliderView(Context context, AttributeSet attrs) {
		super(context, attrs);
		scroller = new Scroller(context);
	}

	@Override
	protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
		int childCount = getChildCount();
		for (int i = 0; i < childCount; ++i) {
			View view = getChildAt(i);
			if (view.getVisibility() != View.GONE) {
				view.layout(0, 0, view.getMeasuredWidth(),
						view.getMeasuredHeight());
			}
		}
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		return true;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (mVelocityTracker == null) {
			mVelocityTracker = VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(event);
		int action = event.getAction();
		if (action == MotionEvent.ACTION_DOWN) {
			x = event.getX();
			//分发事件
			if (isSlided()) {
				dispatched = dispatchTouchEventToView(getChildAt(0), event);
			} else {
				dispatched = dispatchTouchEventToView(getChildAt(1), event);
			}
		} else if (action == MotionEvent.ACTION_MOVE) {
			if (dispatched) {//分发事件
				if (isSlided()) {
					dispatchTouchEventToView(getChildAt(0), event);
				} else {
					dispatchTouchEventToView(getChildAt(1), event);
				}
			} else {//重置第一个子view位置
				float dx = event.getX() - x;
				View view = getChildAt(1);
				int left = (int) (view.getLeft() + dx);
				if (left >= 0) {
					view.layout(left, view.getTop(), view.getWidth() + left,
							view.getTop() + view.getHeight());
				}
			}
			x = event.getX();

		} else if (action == MotionEvent.ACTION_CANCEL
				|| action == MotionEvent.ACTION_UP) {
			if (dispatched) {//分发事件
				if (isSlided()) {
					dispatchTouchEventToView(getChildAt(0), event);
				} else {
					dispatchTouchEventToView(getChildAt(1), event);
				}
			} else {
				//判断速度
				mVelocityTracker.computeCurrentVelocity(1000);
				int velocityX = (int) mVelocityTracker.getXVelocity();
				if (velocityX > VELOCITY_X_SPEED) {
					setSlided(true);
				} else if (velocityX < -VELOCITY_X_SPEED) {
					setSlided(false);
				} else {
					View view = getChildAt(1);
					if (view.getLeft() >= view.getWidth() / 2) {
						setSlided(true);
					} else {
						setSlided(false);
					}
				}
				if (mVelocityTracker != null) {
					mVelocityTracker.recycle();
				}
			}
		}
		return true;
	}

	public boolean isSlided() {
		return slided;
	}

	/**
	 * 设置是否滑动显示菜单状态,并动画滑动效果
	 * @param slided
	 */
	public void setSlided(boolean slided) {
		View view = getChildAt(1);
		startScrollLeftOffset = view.getLeft();
		if (slided) {
			scroller.startScroll(0, getTop(), view.getWidth() * 3 / 4
					- startScrollLeftOffset, 0);
		} else {
			scroller.startScroll(0, getTop(), -startScrollLeftOffset, 0);
		}
		this.slided = slided;
		postInvalidate();
	}

	@Override
	public void computeScroll() {
		if (scroller.computeScrollOffset()) {
			View view = getChildAt(1);
			int left = startScrollLeftOffset + scroller.getCurrX();
			view.layout(left, view.getTop(), left + view.getWidth(),
					view.getHeight());
			postInvalidate();
		}
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		for (int i = 0; i < getChildCount(); ++i) {
			getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
		}
	}

	public boolean dispatchTouchEventToView(View view, MotionEvent ev) {
		try {
			return view.dispatchTouchEvent(ev);
		} catch (Exception e) {
			// 部分机型会抛异常
			e.printStackTrace();
		}
		return false;
	}
}

  ------------------------------------------------------例子

package com.example.viewdemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener,
		OnItemClickListener {
	SliderView sliderView;
	ListView listView;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		sliderView = (SliderView) findViewById(R.id.slider_view);
		Button button1 = (Button) findViewById(R.id.button1);
		Button button2 = (Button) findViewById(R.id.button2);
		button1.setOnClickListener(this);
		button2.setOnClickListener(this);
		listView = (ListView) findViewById(R.id.listView);
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1, new String[] { "GOOD",
						"HAHA", "What is that?", "FUUUUCK" });
		listView.setAdapter(adapter);
		listView.setOnItemClickListener(this);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		return true;
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		sliderView.setSlided(!sliderView.isSlided());
		return true;
	}

	@Override
	public void onClick(View v) {
		Toast.makeText(this, ((Button) v).getText().toString(),
				Toast.LENGTH_LONG).show();
	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
		String string = (String) arg0.getItemAtPosition(arg2);
		Toast.makeText(this, string, Toast.LENGTH_LONG).show();
	}
}

  ----------------------------------------------布局

<LinearLayout 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"
    android:orientation="vertical" >

    <com.example.viewdemo.SliderView
        android:id="@+id/slider_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

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

            <LinearLayout
                android:layout_width="0dip"
                android:layout_height="match_parent"
                android:layout_weight="3"
                android:orientation="vertical" >

                <Button
                    android:id="@+id/button1"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="hello" />

                <ListView
                    android:id="@+id/listView"
                    android:layout_width="match_parent"
                    android:layout_height="0dip"
                    android:layout_weight="1" >
                </ListView>
            </LinearLayout>

            <LinearLayout
                android:layout_width="0dip"
                android:layout_height="match_parent"
                android:layout_weight="1" >
            </LinearLayout>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/black"
            android:gravity="center" >

            <Button
                android:id="@+id/button2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="world" />
        </LinearLayout>
    </com.example.viewdemo.SliderView>

</LinearLayout>

  

posted @ 2013-03-29 14:24  penink  阅读(7853)  评论(0编辑  收藏  举报