首先看一下主activity:
- package grimbo.android.demo.slidingmenu;
-
- import android.app.Activity;
- import android.graphics.Color;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.widget.Button;
-
- public class MainActivity extends Activity {
- private MyHorizontalScrollView scrollView;
- private View leftMenu;
- private View rightMenu;
-
- private View tab01;
- private Button leftButton;
- private Button rightButton;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- LayoutInflater inflater = LayoutInflater.from(this);
- setContentView(inflater.inflate(R.layout.main, null));
-
- scrollView = (MyHorizontalScrollView) findViewById(R.id.myScrollView);
- leftMenu = findViewById(R.id.leftmenu);
- rightMenu = findViewById(R.id.rightmenu);
-
- tab01 = inflater.inflate(R.layout.tab01, null);
- leftButton = (Button) tab01.findViewById(R.id.leftButton);
- rightButton = (Button)tab01.findViewById(R.id.rightButton);
-
- leftButton.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- scrollView.clickLeftButton(leftButton.getMeasuredWidth());
- }
- });
-
- rightButton.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- scrollView.clickRightButton(rightButton.getMeasuredWidth());
- }
- });
-
-
- View leftView = new View(this);
- View rightView = new View(this);
- leftView.setBackgroundColor(Color.TRANSPARENT);
- rightView.setBackgroundColor(Color.TRANSPARENT);
- final View[] children = new View[] {leftView, tab01,rightView };
-
- scrollView.initViews(children, new SizeCallbackForMenu(leftButton),leftMenu,rightMenu);
- }
- }
其中tab01是一个由布局文件tab01.xml定义的view,放置“左边”和“右边”两个按钮
View leftView = new View(this);//左边透明视图
View rightView = new View(this);//右边透明视图
leftView.setBackgroundColor(Color.TRANSPARENT);
rightView.setBackgroundColor(Color.TRANSPARENT);
四句定义两个透明视图,透明视图就是只占用空间,不遮挡放置在其下面的视图
scrollView.initViews把两个透明视图和一个中间的tab视图放入HorizontalScrollView 的LinearLayout里,LinearLayout是横向布局,这样tab移到屏幕可视范围的时候就遮住了底下的leftmenu和rightmenu,当两侧透明视图移入屏幕可视范围的时候,底下的leftmenu或rightmenu就显现出来了,以此实现侧滑效果
然后看一下自定义的滑动类MyHorizontalScrollView
- package grimbo.android.demo.slidingmenu;
-
- import android.content.Context;
- import android.os.Handler;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.GestureDetector;
- import android.view.GestureDetector.SimpleOnGestureListener;
- import android.view.MotionEvent;
- import android.view.VelocityTracker;
- import android.view.View;
- import android.view.ViewGroup;
- import android.view.GestureDetector.OnGestureListener;
- import android.view.ViewTreeObserver.OnGlobalLayoutListener;
- import android.widget.HorizontalScrollView;
- import android.widget.Scroller;
-
- public class MyHorizontalScrollView extends HorizontalScrollView {
-
- private final String tag = "MyHorizontalScrollView";
-
- private MyHorizontalScrollView me;
- private View leftMenu;
- private View rightMenu;
- private boolean leftMenuOut = false;
- private boolean rightMenuOut = false;
- private final int ENLARGE_WIDTH = 20;
-
- public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init(context);
- }
-
- public MyHorizontalScrollView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(context);
- }
-
- public MyHorizontalScrollView(Context context) {
- super(context);
- init(context);
- }
-
- void init(Context context) {
-
-
-
- me = this;
- me.setVisibility(View.INVISIBLE);
- }
-
-
- public void initViews(View[] children, SizeCallback sizeCallback,View leftMenu,View rightMenu) {
- this.leftMenu = leftMenu;
- this.rightMenu = rightMenu;
- ViewGroup parent = (ViewGroup) getChildAt(0);
-
-
- for (int i = 0; i < children.length; i++) {
- children[i].setVisibility(View.INVISIBLE);
- parent.addView(children[i]);
- }
-
-
-
- OnGlobalLayoutListener listener = new MyOnGlobalLayoutListener(parent, children, sizeCallback);
- getViewTreeObserver().addOnGlobalLayoutListener(listener);
- }
-
-
-
-
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
-
- return false;
- }
-
-
- class MyOnGlobalLayoutListener implements OnGlobalLayoutListener {
- ViewGroup parent;
- View[] children;
- int scrollToViewPos = 0;
- SizeCallback sizeCallback;
-
-
- public MyOnGlobalLayoutListener(ViewGroup parent, View[] children, SizeCallback sizeCallback) {
- this.parent = parent;
- this.children = children;
- this.sizeCallback = sizeCallback;
- }
-
- @Override
- public void onGlobalLayout() {
-
- me.getViewTreeObserver().removeGlobalOnLayoutListener(this);
-
- sizeCallback.onGlobalLayout();
-
- parent.removeViewsInLayout(0, children.length);
-
- final int w = me.getMeasuredWidth();
- final int h = me.getMeasuredHeight();
-
- int[] dims = new int[2];
- scrollToViewPos = 0;
- for (int i = 0; i < children.length; i++) {
- sizeCallback.getViewSize(i, w, h, dims);
- children[i].setVisibility(View.VISIBLE);
- parent.addView(children[i], dims[0], dims[1]);
- if (i == 0) {
- scrollToViewPos += dims[0];
- }
- Log.d(tag, children[i]+": w=" + dims[0] + ", h=" + dims[1]);
- Log.d(tag, "scrollToViewIdx:"+0+",scrollToViewPos:"+scrollToViewPos);
- }
-
-
- new Handler().post(new Runnable() {
- @Override
- public void run() {
- me.scrollBy(scrollToViewPos,0);
-
- me.setVisibility(View.VISIBLE);
- leftMenu.setVisibility(View.VISIBLE);
- rightMenu.setVisibility(View.VISIBLE);
- }
- });
- }
- }
-
-
- public void clickLeftButton(int leftButtonWidth){
-
- rightMenu.setVisibility(View.GONE);
- leftMenu.setVisibility(View.VISIBLE);
- int menuWidth = leftMenu.getMeasuredWidth()-(leftButtonWidth+ENLARGE_WIDTH);
- System.out.println("leftmenuWidth:"+menuWidth);
- if (!leftMenuOut) {
- int left = 0;
- me.smoothScrollTo(left, 0);
- } else {
- int left = menuWidth;
- me.smoothScrollTo(left, 0);
- }
- leftMenuOut = !leftMenuOut;
- }
-
-
- public void clickRightButton(int rightButtonWidth){
- <span style="white-space:pre"> </span>leftMenu.setVisibility(View.GONE);
- rightMenu.setVisibility(View.VISIBLE);
- int menuWidth = rightMenu.getMeasuredWidth() - (rightButtonWidth+ENLARGE_WIDTH);
- if (!rightMenuOut) {
- int right = menuWidth + me.getMeasuredWidth();
- System.out.println("rightmenuWidth:"+right);
- me.smoothScrollTo(right, 0);
- } else {
- int right = menuWidth;
- System.out.println("rightmenuWidth:"+right);
- me.smoothScrollTo(right, 0);
- }
- rightMenuOut = !rightMenuOut;
- }
-
-
-
- @Override
- <span style="white-space:pre"> </span>public boolean onTouchEvent(MotionEvent ev) {
- return false;
- }
-
-
- public interface SizeCallback {
-
- public void onGlobalLayout();
-
- public void getViewSize(int idx, int w, int h, int[] dims);
- }
- }
initViews:把传入的view加入第0个viewgroup,也就是xml中配置的LinearLayout中,并把一个MyOnGlobalLayoutListener对象设置为layout变化的观察者,initViews中放入的view只是占了个位置,后面的onGlobalLayout中会重新给这些view分配高和宽并加到LinearLayout中,但是在这之前需要预先放上去以得到某些控件的size(sizeCallback.onGlobalLayout()中),所以需要在这先加一次
onGlobalLayout:作为观察者,会在view的layout发生发生改变时自动调用此方法,由于只需要调用一次,所以方法里第一句就是调用removeGlobalOnLayoutListener,这个方法的主要功能就是把需要加入layout的views按照计算的宽度并加上去,然后调用me.scrollBy(scrollToViewPos,0);使加上去的view偏移,让tab01这个view偏移到屏幕可视范围中
clickLeftButton,clickRightButton:点击左边和右边的按钮时,控制MyHorizontalScrollView自身移动,显示出侧面相应的功能菜单,注意在移动之前,最左侧和最右侧是屏幕外的leftview和rightview,所以:
int left = 0;
me.smoothScrollTo(left, 0);
是把leftview移进来,中间的tab01向右移
完整源码下载地址:
http://download.csdn.net/detail/lamp_zy/4494989