`
bk_lin
  • 浏览: 335394 次
社区版块
存档分类
最新评论

可动态布局的Android抽屉之完整篇

阅读更多

本文来自http://blog.csdn.net/hellogv/ ,欢迎转摘,引用必须注明出处!      

       上次介绍了基础篇,讲解了自定义抽屉控件的基础实现,这次就在基础篇的基础上加入拖拉功能。拖拉功能基于GestureDetector,GestureDetector的基本使用方式不是本文介绍的重点,有兴趣的童鞋可以上网查询相关的教程。

       本文的抽屉控件相对于基础篇的抽屉控件多了以下功能:

1.支持手势拖拉

2.拖拉到一半时,可以自动展开或者收缩。
具体如下图:

 

 

 

 

 

 

本文的源码可以到这里下载:http://download.csdn.net/detail/hellogv/3642418

只贴出抽屉组件的源码,其他源文件与基础篇的一样:

  1. <span style="font-family:Comic Sans MS;font-size:18px;">public class Panel extends LinearLayout implements GestureDetector.OnGestureListener{  
  2.       
  3.     public interface PanelClosedEvent {  
  4.         void onPanelClosed(View panel);  
  5.     }  
  6.       
  7.     public interface PanelOpenedEvent {  
  8.         void onPanelOpened(View panel);  
  9.     }  
  10.       
  11.     private final static int HANDLE_WIDTH=30;  
  12.     private final static int MOVE_WIDTH=20;  
  13.     private Button btnHandler;  
  14.     private LinearLayout panelContainer;  
  15.     private int mRightMargin=0;  
  16.     private Context mContext;  
  17.     private GestureDetector mGestureDetector;  
  18.     private boolean mIsScrolling=false;  
  19.     private float mScrollX;  
  20.     private PanelClosedEvent panelClosedEvent=null;  
  21.     private PanelOpenedEvent panelOpenedEvent=null;  
  22.       
  23.     public Panel(Context context,View otherView,int width,int height) {  
  24.         super(context);  
  25.         this.mContext=context;  
  26.           
  27.         //定义手势识别  
  28.         mGestureDetector = new GestureDetector(mContext,this);  
  29.         mGestureDetector.setIsLongpressEnabled(false);  
  30.           
  31.         //改变Panel附近组件的属性  
  32.         LayoutParams otherLP=(LayoutParams) otherView.getLayoutParams();  
  33.         otherLP.weight=1;  
  34.         otherView.setLayoutParams(otherLP);  
  35.           
  36.         //设置Panel本身的属性  
  37.         LayoutParams lp=new LayoutParams(width, height);  
  38.         lp.rightMargin=-lp.width+HANDLE_WIDTH;  
  39.         mRightMargin=Math.abs(lp.rightMargin);  
  40.         this.setLayoutParams(lp);  
  41.         this.setOrientation(LinearLayout.HORIZONTAL);  
  42.           
  43.         //设置Handler的属性  
  44.         btnHandler=new Button(context);  
  45.         btnHandler.setLayoutParams(new LayoutParams(HANDLE_WIDTH,height));  
  46.         //btnHandler.setOnClickListener(handlerClickEvent);  
  47.         btnHandler.setOnTouchListener(handlerTouchEvent);  
  48.         this.addView(btnHandler);  
  49.           
  50.         //设置Container的属性  
  51.         panelContainer=new LinearLayout(context);  
  52.         panelContainer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,  
  53.                 LayoutParams.FILL_PARENT));  
  54.         this.addView(panelContainer);  
  55.   
  56.     }  
  57.   
  58.     private View.OnTouchListener handlerTouchEvent=new View.OnTouchListener() {  
  59.           
  60.         @Override  
  61.         public boolean onTouch(View v, MotionEvent event) {  
  62.             if(event.getAction()==MotionEvent.ACTION_UP && //onScroll时的ACTION_UP  
  63.                     mIsScrolling==true)  
  64.             {  
  65.                 LayoutParams lp=(LayoutParams) Panel.this.getLayoutParams();  
  66.                 if (lp.rightMargin >= (-mRightMargin/2)) {//往左超过一半  
  67.                     new AsynMove().execute(new Integer[] { MOVE_WIDTH });// 正数展开  
  68.                 }   
  69.                 else if (lp.rightMargin < (-mRightMargin/2)) {//往右拖拉  
  70.                     new AsynMove().execute(new Integer[] { -MOVE_WIDTH });// 负数收缩  
  71.                 }  
  72.             }  
  73.             return mGestureDetector.onTouchEvent(event);   
  74.         }  
  75.     };  
  76.   
  77.     /** 
  78.      * 定义收缩时的回调函数 
  79.      * @param event 
  80.      */  
  81.     public void setPanelClosedEvent(PanelClosedEvent event)  
  82.     {  
  83.         this.panelClosedEvent=event;  
  84.     }  
  85.       
  86.     /** 
  87.      * 定义展开时的回调函数 
  88.      * @param event 
  89.      */  
  90.     public void setPanelOpenedEvent(PanelOpenedEvent event)  
  91.     {  
  92.         this.panelOpenedEvent=event;  
  93.     }  
  94.       
  95.     /** 
  96.      * 把View放在Panel的Container 
  97.      * @param v 
  98.      */  
  99.     public void fillPanelContainer(View v)  
  100.     {  
  101.         panelContainer.addView(v);  
  102.     }  
  103.       
  104.     /** 
  105.      * 异步移动Panel 
  106.      * @author hellogv  
  107.      */  
  108.     class AsynMove extends AsyncTask<Integer, Integer, Void> {  
  109.   
  110.         @Override  
  111.         protected Void doInBackground(Integer... params) {  
  112.             int times;  
  113.             if (mRightMargin % Math.abs(params[0]) == 0)// 整除  
  114.                 times = mRightMargin / Math.abs(params[0]);  
  115.             else  
  116.                 // 有余数  
  117.                 times = mRightMargin / Math.abs(params[0]) + 1;  
  118.   
  119.             for (int i = 0; i < times; i++) {  
  120.                 publishProgress(params);  
  121.                 try {  
  122.                     Thread.sleep(Math.abs(params[0]));  
  123.                 } catch (InterruptedException e) {  
  124.                     // TODO Auto-generated catch block  
  125.                     e.printStackTrace();  
  126.                 }  
  127.             }  
  128.             return null;  
  129.         }  
  130.   
  131.         @Override  
  132.         protected void onProgressUpdate(Integer... params) {  
  133.             LayoutParams lp = (LayoutParams) Panel.this.getLayoutParams();  
  134.             if (params[0] < 0)  
  135.                 lp.rightMargin = Math.max(lp.rightMargin + params[0],  
  136.                         (-mRightMargin));  
  137.             else  
  138.                 lp.rightMargin = Math.min(lp.rightMargin + params[0], 0);  
  139.   
  140.             if(lp.rightMargin==0 && panelOpenedEvent!=null){//展开之后  
  141.                 panelOpenedEvent.onPanelOpened(Panel.this);//调用OPEN回调函数  
  142.             }  
  143.             else if(lp.rightMargin==-(mRightMargin) && panelClosedEvent!=null){//收缩之后  
  144.                 panelClosedEvent.onPanelClosed(Panel.this);//调用CLOSE回调函数  
  145.             }  
  146.             Panel.this.setLayoutParams(lp);  
  147.         }  
  148.     }  
  149.   
  150.     @Override  
  151.     public boolean onDown(MotionEvent e) {  
  152.         mScrollX=0;  
  153.         mIsScrolling=false;  
  154.         return false;  
  155.     }  
  156.   
  157.     @Override  
  158.     public boolean onSingleTapUp(MotionEvent e) {  
  159.         LayoutParams lp = (LayoutParams) Panel.this.getLayoutParams();  
  160.         if (lp.rightMargin < 0)// CLOSE的状态  
  161.             new AsynMove().execute(new Integer[] { MOVE_WIDTH });// 正数展开  
  162.         else if (lp.rightMargin >= 0)// OPEN的状态  
  163.             new AsynMove().execute(new Integer[] { -MOVE_WIDTH });// 负数收缩  
  164.         return false;  
  165.     }  
  166.       
  167.     @Override  
  168.     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,  
  169.             float distanceY) {  
  170.         mIsScrolling=true;  
  171.         mScrollX+=distanceX;  
  172.           
  173.         LayoutParams lp=(LayoutParams) Panel.this.getLayoutParams();  
  174.         if (lp.rightMargin < -1 && mScrollX > 0) {//往左拖拉  
  175.             lp.rightMargin = Math.min((lp.rightMargin + (int) mScrollX),0);  
  176.             Panel.this.setLayoutParams(lp);  
  177.             Log.e("onScroll",lp.rightMargin+"");  
  178.         }   
  179.         else if (lp.rightMargin > -(mRightMargin) && mScrollX < 0) {//往右拖拉  
  180.             lp.rightMargin = Math.max((lp.rightMargin + (int) mScrollX),-mRightMargin);  
  181.             Panel.this.setLayoutParams(lp);  
  182.         }  
  183.           
  184.         if(lp.rightMargin==0 && panelOpenedEvent!=null){//展开之后  
  185.             panelOpenedEvent.onPanelOpened(Panel.this);//调用OPEN回调函数  
  186.         }  
  187.         else if(lp.rightMargin==-(mRightMargin) && panelClosedEvent!=null){//收缩之后  
  188.             panelClosedEvent.onPanelClosed(Panel.this);//调用CLOSE回调函数  
  189.         }  
  190.         Log.e("onScroll",lp.rightMargin+"");  
  191.           
  192.         return false;  
  193.     }  
  194.       
  195.     @Override  
  196.     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,  
  197.             float velocityY) {return false;}  
  198.     @Override  
  199.     public void onLongPress(MotionEvent e) {}  
  200.     @Override  
  201.     public void onShowPress(MotionEvent e) {}  
  202.   
  203. }  
  204. </span>  


 

分享到:
评论

相关推荐

    “可动态布局”的Android抽屉组件之完整篇

    本篇将深入探讨如何创建一个可动态布局的Android抽屉组件,提供一个完整的实现案例源码。 首先,抽屉组件的基本概念:DrawerLayout是Android提供的一个视图容器,它可以包含两个主要区域——主内容视图和一个或多个...

    “可动态布局”的Android抽屉组件之构建基础

    本篇将深入探讨如何构建一个支持动态布局的Android抽屉组件,以ExPanel(1)为例。 首先,抽屉组件的核心是`android.support.v4.widget.DrawerLayout`,它是Android Support Library中的一个控件,用于创建滑动抽屉...

    Android抽屉效果上下抽屉

    `&lt;android.support.v4.widget.DrawerLayout&gt;` 作为根元素,包含主布局和抽屉布局。抽屉视图使用 `android:layout_gravity` 属性来定位,如 "start" 或 "end" 表示从左侧或右侧滑出。 6. **数据绑定和菜单项点击事件...

    可左右两侧挤压傍边布局的Android抽屉

    在Android开发中,"可左右两侧挤压傍边布局的Android抽屉"是一种常见的设计模式,通常用于实现侧滑菜单效果。这种布局允许用户从屏幕的边缘向内滑动,显示隐藏的内容,比如导航选项或者更多功能。在Android的UI设计...

    Android 抽屉实现

    首先,Android抽屉的实现主要依赖于`SlidingDrawer`组件(尽管在较新的API级别中已被弃用)或者`NavigationView`结合`DrawerLayout`。在这个案例中,`slidingdrawer`可能是指一个包含实现抽屉功能的源代码文件。`...

    Android之抽屉效果的下拉菜单(上下伸缩和展开)

    通过以上步骤,你可以创建一个具有上下伸缩和展开效果的Android抽屉下拉菜单。这个过程中,不断优化用户体验,让交互更加自然流畅,是提升应用品质的关键。同时,持续学习和分享新的实现方式,也是提升个人技能的...

    android抽屉结合Fragment

    总的来说,Android抽屉结合`Fragment`是一种常见的应用设计模式,它提供了良好的用户体验和高效的导航结构。开发者需要熟悉`NavigationView`和`DrawerLayout`的使用,以及如何与`Fragment`协作,才能实现流畅的抽屉...

    Android下拉抽屉效果

    本篇文章将详细解析如何在Android4.4中创建一个下拉抽屉效果。 首先,下拉抽屉在Android中通常通过`NavigationView`或者`SlidingPaneLayout`来实现。`NavigationView`是Google推荐用来构建侧边栏菜单的组件,而`...

    Android 抽屉效果的实现

    在Android应用开发中,抽屉效果(DrawerLayout)是一种常见的设计模式,用于...以上就是关于Android抽屉效果实现的基本知识和步骤。在实际项目中,你可能需要根据具体需求进行调整,例如添加动画效果、定制菜单样式等。

    android类似双向抽屉效果实现

    `DrawerLayout`是Android SDK中的一个布局容器,它可以容纳一个或两个抽屉视图,通常是从屏幕左侧或右侧滑出。在XML布局文件中,你可以将主内容视图和抽屉视图分别作为`DrawerLayout`的子元素来设置。 以下是一个...

    android 多方向抽屉

    描述中的"android多方向抽屉drawer,上下左右均可"表明我们将关注如何实现一个可以沿着屏幕四个边界的抽屉。在Android中,虽然官方的`android.widget.SlidingDrawer`类已经被废弃,但开发者仍然可以通过自定义视图...

    android抽屉组件实例

    以上就是关于“android抽屉组件实例”的核心知识点。通过学习和实践这个实例,初学者不仅可以掌握抽屉组件的基本用法,还能进一步理解Android布局和事件处理机制,为今后的Android开发打下坚实的基础。记得在实际...

    android抽屉效果源码

    总的来说,这个“android抽屉效果源码”是一个很好的学习资源,它涵盖了Android手势检测、视图动画、自定义布局等多个关键知识点。通过分析和运行这个示例,开发者可以深入理解Android滑动抽屉的实现原理,并将其...

    从gitHub上整理出Android抽屉效果,包括左滑,右滑,上滑,下滑,想要实现的任何菜单效果都有

    这个从gitHub上整理的Android抽屉效果项目,涵盖了左滑、右滑、上滑和下滑等多种交互方式,为开发者提供了实现各种菜单效果的工具。 首先,我们来了解一下抽屉布局的基本概念。抽屉布局(DrawerLayout)是Android ...

    Android滑动抽屉示例

    滑动抽屉通常包含在一个Activity的布局文件中,利用`android.support.v4.widget.DrawerLayout`作为根视图。`DrawerLayout`是Android支持库的一部分,用于实现这种侧滑菜单效果。它可以承载两个子视图:主要内容视图...

    android UI 抽屉效果的实现及使用

    以上就是使用`DrawerLayout`和`RecyclerView`实现Android抽屉效果的基本流程。实际开发中,你可能还需要根据具体需求进行调整,比如添加自定义头部视图、实现下拉刷新等高级功能。熟练掌握这些组件的使用,能帮助...

    超爽的android抽屉效果.rar

    Android抽屉效果的核心组件是`NavigationView`和`DrawerLayout`,它们是Android SDK中的两个关键布局组件。 1. **NavigationView**: 这是一个用于创建侧滑菜单的视图组件。它可以显示一个包含头像、用户名、菜单项...

    Android 抽屉fragment实现demo

    本示例"Android抽屉fragment实现demo"着重展示了如何使用Fragment来构建这种交互效果,并且包含了抽屉的进入和退出动画,使得用户体验更为流畅。 首先,抽屉功能的实现主要依赖于`android.support.v4.widget....

    android各种抽屉样式

    在Android应用开发中,...总结,"android各种抽屉样式"项目提供了一个学习和参考Android抽屉实现的宝贵资源。通过研究和实践,开发者可以了解如何根据需求和设计规范创建多样化、高效的抽屉样式,提升应用的用户体验。

Global site tag (gtag.js) - Google Analytics