HardBirch

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

时间:11-09-28 栏目:安卓入门与提高 作者:张飞不张,文采横飞 评论:36 点击: 10,926 次

    

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

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

1.支持手势拖拉

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

 

 

 

 

 

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

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

public class Panel extends LinearLayout implements GestureDetector.OnGestureListener{ public interface PanelClosedEvent { void onPanelClosed(View panel); } public interface PanelOpenedEvent { void onPanelOpened(View panel); } private final static int HANDLE_WIDTH=30; private final static int MOVE_WIDTH=20; private Button btnHandler; private LinearLayout panelContainer; private int mRightMargin=0; private Context mContext; private GestureDetector mGestureDetector; private boolean mIsScrolling=false; private float mScrollX; private PanelClosedEvent panelClosedEvent=null; private PanelOpenedEvent panelOpenedEvent=null; public Panel(Context context,View otherView,int width,int height) { super(context); this.mContext=context; //定义手势识别 mGestureDetector = new GestureDetector(mContext,this); mGestureDetector.setIsLongpressEnabled(false); //改变Panel附近组件的属性 LayoutParams otherLP=(LayoutParams) otherView.getLayoutParams(); otherLP.weight=1; otherView.setLayoutParams(otherLP); //设置Panel本身的属性 LayoutParams lp=new LayoutParams(width, height); lp.rightMargin=-lp.width+HANDLE_WIDTH; mRightMargin=Math.abs(lp.rightMargin); this.setLayoutParams(lp); this.setOrientation(LinearLayout.HORIZONTAL); //设置Handler的属性 btnHandler=new Button(context); btnHandler.setLayoutParams(new LayoutParams(HANDLE_WIDTH,height)); //btnHandler.setOnClickListener(handlerClickEvent); btnHandler.setOnTouchListener(handlerTouchEvent); this.addView(btnHandler); //设置Container的属性 panelContainer=new LinearLayout(context); panelContainer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); this.addView(panelContainer); } private View.OnTouchListener handlerTouchEvent=new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(event.getAction()==MotionEvent.ACTION_UP && //onScroll时的ACTION_UP mIsScrolling==true) { LayoutParams lp=(LayoutParams) Panel.this.getLayoutParams(); if (lp.rightMargin >= (-mRightMargin/2)) {//往左超过一半 new AsynMove().execute(new Integer[] { MOVE_WIDTH });// 正数展开 } else if (lp.rightMargin < (-mRightMargin/2)) {//往右拖拉 new AsynMove().execute(new Integer[] { -MOVE_WIDTH });// 负数收缩 } } return mGestureDetector.onTouchEvent(event); } }; /** * 定义收缩时的回调函数 * @param event */ public void setPanelClosedEvent(PanelClosedEvent event) { this.panelClosedEvent=event; } /** * 定义展开时的回调函数 * @param event */ public void setPanelOpenedEvent(PanelOpenedEvent event) { this.panelOpenedEvent=event; } /** * 把View放在Panel的Container * @param v */ public void fillPanelContainer(View v) { panelContainer.addView(v); } /** * 异步移动Panel * @author hellogv */ class AsynMove extends AsyncTask<Integer, Integer, Void> { @Override protected Void doInBackground(Integer... params) { int times; if (mRightMargin % Math.abs(params[0]) == 0)// 整除 times = mRightMargin / Math.abs(params[0]); else // 有余数 times = mRightMargin / Math.abs(params[0]) + 1; for (int i = 0; i < times; i++) { publishProgress(params); try { Thread.sleep(Math.abs(params[0])); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } @Override protected void onProgressUpdate(Integer... params) { LayoutParams lp = (LayoutParams) Panel.this.getLayoutParams(); if (params[0] < 0) lp.rightMargin = Math.max(lp.rightMargin + params[0], (-mRightMargin)); else lp.rightMargin = Math.min(lp.rightMargin + params[0], 0); if(lp.rightMargin==0 && panelOpenedEvent!=null){//展开之后 panelOpenedEvent.onPanelOpened(Panel.this);//调用OPEN回调函数 } else if(lp.rightMargin==-(mRightMargin) && panelClosedEvent!=null){//收缩之后 panelClosedEvent.onPanelClosed(Panel.this);//调用CLOSE回调函数 } Panel.this.setLayoutParams(lp); } } @Override public boolean onDown(MotionEvent e) { mScrollX=0; mIsScrolling=false; return false; } @Override public boolean onSingleTapUp(MotionEvent e) { LayoutParams lp = (LayoutParams) Panel.this.getLayoutParams(); if (lp.rightMargin < 0)// CLOSE的状态 new AsynMove().execute(new Integer[] { MOVE_WIDTH });// 正数展开 else if (lp.rightMargin >= 0)// OPEN的状态 new AsynMove().execute(new Integer[] { -MOVE_WIDTH });// 负数收缩 return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { mIsScrolling=true; mScrollX+=distanceX; LayoutParams lp=(LayoutParams) Panel.this.getLayoutParams(); if (lp.rightMargin < -1 && mScrollX > 0) {//往左拖拉 lp.rightMargin = Math.min((lp.rightMargin + (int) mScrollX),0); Panel.this.setLayoutParams(lp); Log.e("onScroll",lp.rightMargin+""); } else if (lp.rightMargin > -(mRightMargin) && mScrollX < 0) {//往右拖拉 lp.rightMargin = Math.max((lp.rightMargin + (int) mScrollX),-mRightMargin); Panel.this.setLayoutParams(lp); } if(lp.rightMargin==0 && panelOpenedEvent!=null){//展开之后 panelOpenedEvent.onPanelOpened(Panel.this);//调用OPEN回调函数 } else if(lp.rightMargin==-(mRightMargin) && panelClosedEvent!=null){//收缩之后 panelClosedEvent.onPanelClosed(Panel.this);//调用CLOSE回调函数 } Log.e("onScroll",lp.rightMargin+""); return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {return false;} @Override public void onLongPress(MotionEvent e) {} @Override public void onShowPress(MotionEvent e) {} } 

 

 

 

声明: 本文由( 张飞不张,文采横飞 )原创编译,转载请保留链接: 可动态布局的Android抽屉之完整篇

可动态布局的Android抽屉之完整篇:目前有36 条留言

  1. 36楼
    kf156:

    来学习了,顶起

    2011-09-28 09:38 [回复]
  2. 35楼
    xyylchq:

    接着顶起

    2011-09-28 09:42 [回复]
  3. 正好想了解一下 view的滑动 学习一下

    2011-09-28 09:44 [回复]
  4. 33楼
    hmc1985:

    学习一下!

    2011-09-28 09:45 [回复]
  5. 32楼
    w2525700:

    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

    2011-09-28 10:38 [回复]
  6. 挺一吧 牛呀

    2011-09-28 20:59 [回复]
  7. 30楼
    nos19880918:

    还用到了异步啊,很高深,学习了

    2011-09-29 09:31 [回复]
  8. 29楼
    shampire:

    学习啊~

    2011-09-29 11:39 [回复]
  9. 28楼
    her2006:

    学习下。

    2011-09-29 15:14 [回复]
  10. 27楼
    M_ChangGong:

    很棒,有时间研究一下。

    2011-09-29 15:33 [回复]
  11. 26楼
    certificate:

    很实用, 学习了.

    2011-10-01 12:23 [回复]
  12. 25楼
    guoke16888:

    牛。

    2011-10-02 07:23 [回复]
  13. 想问博主一个问题,您用过VNC么?

    2011-10-19 16:26 [回复]
  14. 23楼
    hellogv:

    [reply]cdfylhyxytzyxx[/reply]
    VNC真么用过

    2011-10-20 09:10 [回复]
  15. [reply]hellogv[/reply]
    您能加我QQ一下么,老师让我一个人弄android,有些问题需要向您请教~

    2011-10-21 10:02 [回复]
  16. 21楼
    allenqch:

    国威,你好。急需您的专业意见来提升一个带表格的android app的用户体验。我的电话186 2155 0185. 请见信回复,万分感谢!

    2011-11-09 07:36 [回复]
  17. 楼主很强大 想加你好友

    2011-11-15 17:17 [回复]
  18. 19楼
    hellogv:

    [reply]allenqch[/reply]
    。。。。。。你开个bbs帖子,我去回复好了

    2011-11-15 19:54 [回复]
  19. 18楼
    chenlijie88:

    你好,请问你有安卓平台的健康软件吗
    谢谢
    陈先生13682404658
    sjs618@126.com

    2011-12-02 19:51 [回复]
  20. 17楼
    chenlijie88:

    你好,请问你有安卓平台的健康软件吗.分析显示血氧、血压、心电、体温等,我可以购买。

    谢谢
    陈先生13682404658
    sjs618@126.com

    2011-12-02 19:54 [回复]
  21. 16楼
    kingvan1990:

    [reply]chenlijie88[/reply]
    这个需要硬件检测电路跟手机搭配的吧,手机上没那么多传感器。

    2011-12-07 10:52 [回复]
  22. 15楼
    read_act:

    你好,你 写得非常好,
    请问你在Panel中用到了两个接口, 调用者实现并最终执行自己的方法, 这种模式一定有它的好处吧, 是什么呢 ?
    谢谢!

    2011-12-07 14:42 [回复]
  23. 14楼
    hellogv:

    [reply]read_act[/reply]
    回调函数的作用。。。你上网搜搜就知道了。。。

    2011-12-07 23:48 [回复]
  24. 13楼
    fongko:

    [reply]hellogv[/reply]
    你好,请教个问题, 我现在做的一个抽屉菜单,用的imagebutton 有2张图片,按下和松开的时候会改变状态,是在代码中设置的,在应用中有个主题的功能,当更换主题后,抽屉按钮就变小了, 最开始的图片是默认的,更换的图片是从服务器上下载的。 请问,下载后更换主题抽屉按钮变小了怎么解决?
    注:图片大小尺寸都是一样的,颜色不同而已

    2011-12-08 11:21 [回复]
  25. 12楼
    hellogv:

    [reply]fongko[/reply]
    用ImageView,他有属性固定大小拉升

    2011-12-10 00:05 [回复]
  26. 11楼
    bawanglb:

    今天突然网上看见了2011博客大赛,突然想起了你,来看看,呵呵,祝楼主愉快。。。

    2011-12-10 20:35 [回复]
  27. 10楼
    hellogv:

    [reply]bawanglb[/reply]
    不争名逐利,有好东西可以分享就行了

    2011-12-15 22:31 [回复]
  28. 9楼
    ziwawang:

    刚接触android.学习了。谢谢

    2012-01-24 22:32 [回复]
  29. 8楼
    zlx1991:

    好给力的博主,,,,,,我要把精髓都学到

    2012-03-12 22:15 [回复]
  30. 7楼
    wqy8517020:

    能加我QQ吗?794475486

    2012-03-13 21:04 [回复]
  31. 6楼
    hellogv:

    [reply]wqy8517020[/reply]
    这个不太方便

    2012-03-14 11:14 [回复]
  32. 5楼
    einstein82:

    mk

    2012-03-19 14:29 [回复]
  33. dingsad

    2012-03-26 14:35 [回复]
  34. 地板
    FreeTymeKiyan:

    楼主的分享精神让人佩服!内容也十分给力!
    想问楼主如何才能实现像海豚浏览器那样的UI,在左边缘区域向右滑动就能显示一个导航。导航栏不占满全屏,并且首页在这个导航栏的下面,丢失焦点,点击可以直接切换回首页。
    一直想不到解决方案啊,求楼主指点!
    欢迎邮件交流FreeTymeSunKiyan@gmail.com

    2012-05-10 01:54 [回复]
  35. 板凳
    logo616:

    mScrollX+=distanceX;

    LayoutParams lp=(LayoutParams) Panel.this.getLayoutParams();
    if (lp.rightMargin < -1 && mScrollX > 0) {//往左拖拉

    根据mScrollX 来判断左右滑动吗?这原理到底是怎样的,能说一下吗

    2012-06-04 22:44 [回复]
  36. 沙发
    kysl_sxp:

    谢谢楼主提供的源码

    2012-08-09 15:41 [回复]

发表评论


QQ群互动

Linux系统与内核学习群:194051772

WP建站技术学习交流群:194062106

魔豆之路QR

魔豆的Linux内核之路

魔豆的Linux内核之路

优秀工程师当看优秀书籍

优秀程序员,要看优秀书!

赞助商广告

友荐云推荐