简单的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>