一个侧屏滑动操作的实例(仿遇见)之三:代码分析

一个侧屏滑动操作的实例(仿遇见)之三:代码分析

分类: android UI android view   134人阅读  评论(0)  收藏  举报


首先看一下主activity:

[java]  view plain copy
  1. package grimbo.android.demo.slidingmenu;  
  2.   
  3. import android.app.Activity;  
  4. import android.graphics.Color;  
  5. import android.os.Bundle;  
  6. import android.view.LayoutInflater;  
  7. import android.view.View;  
  8. import android.widget.Button;  
  9.   
  10. public class MainActivity extends Activity {  
  11.     private MyHorizontalScrollView scrollView;  
  12.     private View leftMenu;  
  13.     private View rightMenu;  
  14.       
  15.     private View tab01;  
  16.     private Button leftButton;  
  17.     private Button rightButton;  
  18.   
  19.     @Override  
  20.     public void onCreate(Bundle savedInstanceState) {  
  21.         super.onCreate(savedInstanceState);  
  22.   
  23.         LayoutInflater inflater = LayoutInflater.from(this);  
  24.         setContentView(inflater.inflate(R.layout.main, null));  
  25.   
  26.         scrollView = (MyHorizontalScrollView) findViewById(R.id.myScrollView);  
  27.         leftMenu = findViewById(R.id.leftmenu);  
  28.         rightMenu = findViewById(R.id.rightmenu);  
  29.           
  30.         tab01 = inflater.inflate(R.layout.tab01, null);  
  31.         leftButton = (Button) tab01.findViewById(R.id.leftButton);  
  32.         rightButton = (Button)tab01.findViewById(R.id.rightButton);  
  33.           
  34.         leftButton.setOnClickListener(new View.OnClickListener() {  
  35.               
  36.             @Override  
  37.             public void onClick(View v) {  
  38.                 scrollView.clickLeftButton(leftButton.getMeasuredWidth());  
  39.             }  
  40.         });  
  41.           
  42.         rightButton.setOnClickListener(new View.OnClickListener() {  
  43.               
  44.             @Override  
  45.             public void onClick(View v) {  
  46.                 scrollView.clickRightButton(rightButton.getMeasuredWidth());  
  47.             }  
  48.         });  
  49.           
  50.   
  51.         View leftView = new View(this);//左边透明视图  
  52.         View rightView = new View(this);//右边透明视图  
  53.         leftView.setBackgroundColor(Color.TRANSPARENT);  
  54.         rightView.setBackgroundColor(Color.TRANSPARENT);  
  55.         final View[] children = new View[] {leftView, tab01,rightView };  
  56.         //初始化滚动布局  
  57.         scrollView.initViews(children, new SizeCallbackForMenu(leftButton),leftMenu,rightMenu);          
  58.     }  
  59. }  

其中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

[java]  view plain copy
  1. package grimbo.android.demo.slidingmenu;  
  2.   
  3. import android.content.Context;  
  4. import android.os.Handler;  
  5. import android.util.AttributeSet;  
  6. import android.util.Log;  
  7. import android.view.GestureDetector;  
  8. import android.view.GestureDetector.SimpleOnGestureListener;  
  9. import android.view.MotionEvent;  
  10. import android.view.VelocityTracker;  
  11. import android.view.View;  
  12. import android.view.ViewGroup;  
  13. import android.view.GestureDetector.OnGestureListener;  
  14. import android.view.ViewTreeObserver.OnGlobalLayoutListener;  
  15. import android.widget.HorizontalScrollView;  
  16. import android.widget.Scroller;  
  17.   
  18. public class MyHorizontalScrollView extends HorizontalScrollView {  
  19.       
  20.     private final String tag = "MyHorizontalScrollView";  
  21.       
  22.     private MyHorizontalScrollView me;//当前控件  
  23.     private View leftMenu;//左边菜单  
  24.     private View rightMenu;//右边菜单  
  25.     private boolean leftMenuOut = false;//左边菜单状态  
  26.     private boolean rightMenuOut = false;//左边菜单状态  
  27.     private final int ENLARGE_WIDTH = 20;//扩展宽度  
  28.       
  29.     public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {  
  30.         super(context, attrs, defStyle);  
  31.         init(context);  
  32.     }  
  33.   
  34.     public MyHorizontalScrollView(Context context, AttributeSet attrs) {  
  35.         super(context, attrs);  
  36.         init(context);  
  37.     }  
  38.   
  39.     public MyHorizontalScrollView(Context context) {  
  40.         super(context);  
  41.         init(context);  
  42.     }  
  43.   
  44.     void init(Context context) {  
  45.         // remove the fading as the HSV looks better without it  
  46.         //setHorizontalFadingEdgeEnabled(true);  
  47.         //setVerticalFadingEdgeEnabled(true);  
  48.         me = this;  
  49.         me.setVisibility(View.INVISIBLE);  
  50.     }  
  51.       
  52.       
  53.     public void initViews(View[] children, SizeCallback sizeCallback,View leftMenu,View rightMenu) {  
  54.         this.leftMenu = leftMenu;  
  55.         this.rightMenu = rightMenu;  
  56.         ViewGroup parent = (ViewGroup) getChildAt(0);  
  57.   
  58.         // Add all the children, but add them invisible so that the layouts are calculated, but you can't see the Views  
  59.         for (int i = 0; i < children.length; i++) {  
  60.             children[i].setVisibility(View.INVISIBLE);  
  61.             parent.addView(children[i]);  
  62.         }  
  63.   
  64.         // Add a layout listener to this HSV  
  65.         // This listener is responsible for arranging the child views.  
  66.         OnGlobalLayoutListener listener = new MyOnGlobalLayoutListener(parent, children, sizeCallback);  
  67.         getViewTreeObserver().addOnGlobalLayoutListener(listener);  
  68.     }  
  69.   
  70.       
  71.       
  72.       
  73.   
  74.     @Override  
  75.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  76.         // Do not allow touch events.  
  77.         return false;  
  78.     }  
  79.   
  80.   
  81.     class MyOnGlobalLayoutListener implements OnGlobalLayoutListener {  
  82.         ViewGroup parent;  
  83.         View[] children;  
  84.         int scrollToViewPos = 0;  
  85.         SizeCallback sizeCallback;  
  86.   
  87.   
  88.         public MyOnGlobalLayoutListener(ViewGroup parent, View[] children, SizeCallback sizeCallback) {  
  89.             this.parent = parent;  
  90.             this.children = children;  
  91.             this.sizeCallback = sizeCallback;  
  92.         }  
  93.   
  94.         @Override  
  95.         public void onGlobalLayout() {  
  96.   
  97.             me.getViewTreeObserver().removeGlobalOnLayoutListener(this);  
  98.   
  99.             sizeCallback.onGlobalLayout();  
  100.   
  101.             parent.removeViewsInLayout(0, children.length);  
  102.   
  103.             final int w = me.getMeasuredWidth();  
  104.             final int h = me.getMeasuredHeight();  
  105.   
  106.             int[] dims = new int[2];  
  107.             scrollToViewPos = 0;  
  108.             for (int i = 0; i < children.length; i++) {  
  109.                 sizeCallback.getViewSize(i, w, h, dims);  
  110.                 children[i].setVisibility(View.VISIBLE);  
  111.                 parent.addView(children[i], dims[0], dims[1]);  
  112.                 if (i == 0) {  
  113.                     scrollToViewPos += dims[0];  
  114.                 }  
  115.                 Log.d(tag, children[i]+": w=" + dims[0] + ", h=" + dims[1]);  
  116.                 Log.d(tag, "scrollToViewIdx:"+0+",scrollToViewPos:"+scrollToViewPos);  
  117.             }  
  118.   
  119.               
  120.             new Handler().post(new Runnable() {  
  121.                 @Override  
  122.                 public void run() {  
  123.                     me.scrollBy(scrollToViewPos,0);  
  124.                     //因为这些控件默认都为隐藏,控件加载完成后,设置成显示  
  125.                     me.setVisibility(View.VISIBLE);  
  126.                     leftMenu.setVisibility(View.VISIBLE);  
  127.                     rightMenu.setVisibility(View.VISIBLE);  
  128.                 }  
  129.             });  
  130.         }  
  131.     }  
  132.       
  133.   
  134.     public void clickLeftButton(int leftButtonWidth){  
  135.   
  136.     rightMenu.setVisibility(View.GONE);  
  137.     leftMenu.setVisibility(View.VISIBLE);  
  138.         int menuWidth = leftMenu.getMeasuredWidth()-(leftButtonWidth+ENLARGE_WIDTH);  
  139.         System.out.println("leftmenuWidth:"+menuWidth);  
  140.         if (!leftMenuOut) {  
  141.             int left = 0;  
  142.             me.smoothScrollTo(left, 0);  
  143.         } else {  
  144.             int left = menuWidth;  
  145.             me.smoothScrollTo(left, 0);  
  146.         }  
  147.         leftMenuOut = !leftMenuOut;  
  148.     }  
  149.       
  150.   
  151.     public void clickRightButton(int rightButtonWidth){  
  152. <span style="white-space:pre">  </span>leftMenu.setVisibility(View.GONE);  
  153.     rightMenu.setVisibility(View.VISIBLE);  
  154.     int menuWidth = rightMenu.getMeasuredWidth() - (rightButtonWidth+ENLARGE_WIDTH);  
  155.         if (!rightMenuOut) {  
  156.             int right = menuWidth + me.getMeasuredWidth();  
  157.             System.out.println("rightmenuWidth:"+right);  
  158.             me.smoothScrollTo(right, 0);  
  159.         } else {  
  160.             int right = menuWidth;  
  161.             System.out.println("rightmenuWidth:"+right);  
  162.             me.smoothScrollTo(right, 0);  
  163.         }  
  164.         rightMenuOut = !rightMenuOut;  
  165.     }  
  166.       
  167.       
  168.   
  169.     @Override  
  170. <span style="white-space:pre">  </span>public boolean onTouchEvent(MotionEvent ev) {  
  171.         return false;  
  172.     }  
  173.   
  174.   
  175.     public interface SizeCallback {  
  176.   
  177.         public void onGlobalLayout();  
  178.   
  179.         public void getViewSize(int idx, int w, int h, int[] dims);  
  180.     }  
  181. }  
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

你可能感兴趣的:(android,android,UI,view)