当前位置: 代码迷 >> Android >> 可动态格局的Android抽屉之基础
  详细解决方案

可动态格局的Android抽屉之基础

热度:47   发布时间:2016-05-01 20:17:12.0
可动态布局的Android抽屉之基础

?

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

?????? 以前曾经介绍过《Android提高第十九篇之"多方向"抽屉》,当这个抽屉组件不与周围组件发生压挤的情况下(周围组件布局不变),是比较好使的,但是如果需要对周围组件挤压,则用起来欠缺美观了。

?????? 如下图。在对周围压挤的情况下,抽屉是先把周围的组件一次性压挤,再通过动画效果展开/收缩的,这种做法的好处是快速简单,坏处是如果挤压范围过大,则效果生硬。

?

????? 本文实现的自定义抽屉组件,主要针对这种压挤效果做出改良,渐进式压挤周围组件,使得过渡效果更加美观。如下图。

?

?

?

?

?

?

本文实现的抽屉原理是酱紫:

1.抽屉组件主要在屏幕不可视区域,手柄在屏幕边缘的可视区域。即 抽屉.rightMargin=-XXX + 手柄.width

2.指定一个周围组件为可压挤,即LayoutParams.weight=1;当然用户也可以指定多个View.

3.使用AsyncTask来实现弹出/收缩的动画,弹出:抽屉.rightMargin+=XX,收缩:抽屉.rightMargin-=XX

总结,本文的自定义抽屉虽然对压挤周围组件有过渡效果,但是比较耗资源,读者可以针对不同的情况考虑使用。

本文的源码可以到http://download.csdn.net/detail/hellogv/3615686?下载。

接下来贴出本文全部源代码:

main.xml的源码:

[html]?view plaincopyprint?
  1. <span?style="font-family:Comic?Sans?MS;font-size:18px;"><?xml?version="1.0"?encoding="utf-8"?>??
  2. <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
  3. ????android:layout_width="fill_parent"?android:layout_height="fill_parent"??
  4. ????android:id="@+id/container">??
  5. ????<GridView?android:id="@+id/gridview"?android:layout_width="fill_parent"??
  6. ????????android:layout_height="fill_parent"?android:numColumns="auto_fit"??
  7. ????????android:verticalSpacing="10dp"?android:gravity="center"??
  8. ????????android:columnWidth="50dip"?android:horizontalSpacing="10dip"?/>??
  9. </LinearLayout></span>??

GridView的Item.xml的源码:

[html]?view plaincopyprint?
  1. <span?style="font-family:Comic?Sans?MS;font-size:18px;"><?xml?version="1.0"?encoding="utf-8"?>??
  2. <RelativeLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
  3. ????android:layout_height="wrap_content"?android:paddingBottom="4dip"??
  4. ????android:layout_width="fill_parent">??
  5. ????<ImageView?android:layout_height="wrap_content"?android:id="@+id/ItemImage"??
  6. ????????android:layout_width="wrap_content"?android:layout_centerHorizontal="true">??
  7. ????</ImageView>??
  8. ????<TextView?android:layout_width="wrap_content"??
  9. ????????android:layout_below="@+id/ItemImage"?android:layout_height="wrap_content"??
  10. ????????android:text="TextView01"?android:layout_centerHorizontal="true"??
  11. ????????android:id="@+id/ItemText">??
  12. ????</TextView>??
  13. </RelativeLayout>??</span>??

Panel.java是本文核心,抽屉组件的源码,这个抽屉只实现了从右往左的弹出/从左往右的收缩,读者可以根据自己的需要修改源码来改变抽屉动作的方向:

[java]?view plaincopyprint?
  1. <span?style="font-family:Comic?Sans?MS;font-size:18px;">public?class?Panel?extends?LinearLayout{??
  2. ??????
  3. ????public?interface?PanelClosedEvent?{??
  4. ????????void?onPanelClosed(View?panel);??
  5. ????}??
  6. ??????
  7. ????public?interface?PanelOpenedEvent?{??
  8. ????????void?onPanelOpened(View?panel);??
  9. ????}??
  10. ????/**Handle的宽度,与Panel等高*/??
  11. ????private?final?static?int?HANDLE_WIDTH=30;??
  12. ????/**每次自动展开/收缩的范围*/??
  13. ????private?final?static?int?MOVE_WIDTH=20;??
  14. ????private?Button?btnHandle;??
  15. ????private?LinearLayout?panelContainer;??
  16. ????private?int?mRightMargin=0;??
  17. ????private?Context?mContext;??
  18. ????private?PanelClosedEvent?panelClosedEvent=null;??
  19. ????private?PanelOpenedEvent?panelOpenedEvent=null;??
  20. ??
  21. ????/**?
  22. ?????*?otherView自动布局以适应Panel展开/收缩的空间变化?
  23. [email protected]?
  24. ?????*?
  25. ?????*/???
  26. ????public?Panel(Context?context,View?otherView,int?width,int?height)?{??
  27. ????????super(context);??
  28. ????????this.mContext=context;??
  29. ??????
  30. ????????//改变Panel附近组件的属性??
  31. ????????LayoutParams?otherLP=(LayoutParams)?otherView.getLayoutParams();??
  32. ????????otherLP.weight=1;//支持压挤??
  33. ????????otherView.setLayoutParams(otherLP);??
  34. ??????????
  35. ????????//设置Panel本身的属性??
  36. ????????LayoutParams?lp=new?LayoutParams(width,?height);??
  37. ????????lp.rightMargin=-lp.width+HANDLE_WIDTH;//Panel的Container在屏幕不可视区域,Handle在可视区域??
  38. ????????mRightMargin=Math.abs(lp.rightMargin);??
  39. ????????this.setLayoutParams(lp);??
  40. ????????this.setOrientation(LinearLayout.HORIZONTAL);??
  41. ??????????
  42. ????????//设置Handle的属性??
  43. ????????btnHandle=new?Button(context);??
  44. ????????btnHandle.setLayoutParams(new?LayoutParams(HANDLE_WIDTH,height));??
  45. ????????btnHandle.setOnClickListener(new?OnClickListener(){??
  46. ??
  47. ????????????@Override??
  48. ????????????public?void?onClick(View?arg0)?{??
  49. ????????????????LayoutParams?lp?=?(LayoutParams)?Panel.this.getLayoutParams();??
  50. ????????????????if?(lp.rightMargin?<?0)//?CLOSE的状态??
  51. ????????????????????new?AsynMove().execute(new?Integer[]?{?MOVE_WIDTH?});//?正数展开??
  52. ????????????????else?if?(lp.rightMargin?>=?0)//?OPEN的状态??
  53. ????????????????????new?AsynMove().execute(new?Integer[]?{?-MOVE_WIDTH?});//?负数收缩??
  54. ????????????}??
  55. ??????????????
  56. ????????});??
  57. ????????//btnHandle.setOnTouchListener(HandleTouchEvent);??
  58. ????????this.addView(btnHandle);??
  59. ??????????
  60. ????????//设置Container的属性??
  61. ????????panelContainer=new?LinearLayout(context);??
  62. ????????panelContainer.setLayoutParams(new?LayoutParams(LayoutParams.FILL_PARENT,??
  63. ????????????????LayoutParams.FILL_PARENT));??
  64. ????????this.addView(panelContainer);??
  65. ????}??
  66. ??
  67. ????/**?
  68. ?????*?定义收缩时的回调函数?
  69. [email protected]?
  70. ?????*/??
  71. ????public?void?setPanelClosedEvent(PanelClosedEvent?event)??
  72. ????{??
  73. ????????this.panelClosedEvent=event;??
  74. ????}??
  75. ??????
  76. ????/**?
  77. ?????*?定义展开时的回调函数?
  78. [email protected]?
  79. ?????*/??
  80. ????public?void?setPanelOpenedEvent(PanelOpenedEvent?event)??
  81. ????{??
  82. ????????this.panelOpenedEvent=event;??
  83. ????}??
  84. ??????
  85. ????/**?
  86. ?????*?把View放在Panel的Container?
  87. [email protected]?
  88. ?????*/??
  89. ????public?void?fillPanelContainer(View?v)??
  90. ????{??
  91. ????????panelContainer.addView(v);??
  92. ????}??
  93. ??????
  94. ????/**?
  95. ?????*?异步移动Panel?
  96. [email protected]?
  97. ?????*/??
  98. ????class?AsynMove?extends?AsyncTask<Integer,?Integer,?Void>?{??
  99. ??
  100. ????????@Override??
  101. ????????protected?Void?doInBackground(Integer...?params)?{??
  102. ????????????int?times;??
  103. ????????????if?(mRightMargin?%?Math.abs(params[0])?==?0)//?整除??
  104. ????????????????times?=?mRightMargin?/?Math.abs(params[0]);??
  105. ????????????else??
  106. ????????????????//?有余数??
  107. ????????????????times?=?mRightMargin?/?Math.abs(params[0])?+?1;??
  108. ??
  109. ????????????for?(int?i?=?0;?i?<?times;?i++)?{??
  110. ????????????????publishProgress(params);??
  111. ????????????????try?{??
  112. ????????????????????Thread.sleep(Math.abs(params[0]));??
  113. ????????????????}?catch?(InterruptedException?e)?{??
  114. ????????????????????//?TODO?Auto-generated?catch?block??
  115. ????????????????????e.printStackTrace();??
  116. ????????????????}??
  117. ????????????}??
  118. ????????????return?null;??
  119. ????????}??
  120. ??
  121. ????????@Override??
  122. ????????protected?void?onProgressUpdate(Integer...?params)?{??
  123. ????????????LayoutParams?lp?=?(LayoutParams)?Panel.this.getLayoutParams();??
  124. ????????????if?(params[0]?<?0)??
  125. ????????????????lp.rightMargin?=?Math.max(lp.rightMargin?+?params[0],??
  126. ????????????????????????(-mRightMargin));??
  127. ????????????else??
  128. ????????????????lp.rightMargin?=?Math.min(lp.rightMargin?+?params[0],?0);??
  129. ??
  130. ????????????if(lp.rightMargin==0?&&?panelOpenedEvent!=null){//展开之后??
  131. ????????????????panelOpenedEvent.onPanelOpened(Panel.this);//调用OPEN回调函数??
  132. ????????????}??
  133. ????????????else?if(lp.rightMargin==-(mRightMargin)?&&?panelClosedEvent!=null){//收缩之后??
  134. ????????????????panelClosedEvent.onPanelClosed(Panel.this);//调用CLOSE回调函数??
  135. ????????????}??
  136. ????????????Panel.this.setLayoutParams(lp);??
  137. ????????}??
  138. ????}??
  139. ??
  140. }??
  141. </span>??

?

main.java是主控部分,演示了Panel的使用:

[java]?view plaincopyprint?
  1. <span?style="font-family:Comic?Sans?MS;font-size:18px;">public?class?main?extends?Activity?{??
  2. ????public?Panel?panel;??
  3. ????public?LinearLayout?container;??
  4. ????public?GridView?gridview;??
  5. ????public?void?onCreate(Bundle?savedInstanceState)?{??
  6. ????????super.onCreate(savedInstanceState);??
  7. ????????setContentView(R.layout.main);??
  8. ????????this.setTitle("“可动态布局”的抽屉组件之构建基础-----hellogv");??
  9. ????????gridview?=?(GridView)?findViewById(R.id.gridview);??
  10. ????????container=(LinearLayout)findViewById(R.id.container);??
  11. ????????panel=new?Panel(this,gridview,200,LayoutParams.FILL_PARENT);??
  12. ????????container.addView(panel);//加入Panel控件??
  13. ??????????
  14. ????????//新建测试组件??
  15. ????????TextView?tvTest=new?TextView(this);??
  16. ????????tvTest.setLayoutParams(new?LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));??
  17. ????????tvTest.setText("测试组件,红字白底");??
  18. ????????tvTest.setTextColor(Color.RED);??
  19. ????????tvTest.setBackgroundColor(Color.WHITE);??
  20. ????????//加入到Panel里面??
  21. ????????panel.fillPanelContainer(tvTest);??
  22. ??????????
  23. ????????panel.setPanelClosedEvent(panelClosedEvent);??
  24. ????????panel.setPanelOpenedEvent(panelOpenedEvent);??
  25. ??????????
  26. ????????//往GridView填充测试数据??
  27. ????????ArrayList<HashMap<String,?Object>>?lstImageItem?=?new?ArrayList<HashMap<String,?Object>>();??
  28. ????????for?(int?i?=?0;?i?<?100;?i++)?{??
  29. ????????????HashMap<String,?Object>?map?=?new?HashMap<String,?Object>();??
  30. ????????????map.put("ItemImage",?R.drawable.icon);??
  31. ????????????map.put("ItemText",?"NO."?+?String.valueOf(i));??
  32. ????????????lstImageItem.add(map);??
  33. ????????}??
  34. ??
  35. ????????SimpleAdapter?saImageItems?=?new?SimpleAdapter(this,???
  36. ????????????????lstImageItem,??
  37. ????????????????R.layout.item,???
  38. ????????????????new?String[]?{?"ItemImage",?"ItemText"?},??
  39. ????????????????new?int[]?{?R.id.ItemImage,?R.id.ItemText?});??
  40. ????????gridview.setAdapter(saImageItems);??
  41. ????????gridview.setOnItemClickListener(new?ItemClickListener());??
  42. ??????????
  43. ????}??
  44. ??
  45. ????PanelClosedEvent?panelClosedEvent?=new?PanelClosedEvent(){??
  46. ??
  47. ????????@Override??
  48. ????????public?void?onPanelClosed(View?panel)?{??
  49. ????????????Log.e("panelClosedEvent","panelClosedEvent");??
  50. ????????}??
  51. ??????????
  52. ????};??
  53. ??????
  54. ????PanelOpenedEvent?panelOpenedEvent?=new?PanelOpenedEvent(){??
  55. ??
  56. ????????@Override??
  57. ????????public?void?onPanelOpened(View?panel)?{??
  58. ????????????Log.e("panelOpenedEvent","panelOpenedEvent");??
  59. ????????}??
  60. ??????????
  61. ????};??
  62. ??????
  63. ????class?ItemClickListener?implements?OnItemClickListener?{??
  64. ????????@Override??
  65. ????????public?void?onItemClick(AdapterView<?>?arg0,View?arg1,?int?arg2,?long?arg3)?{??
  66. ????????????@SuppressWarnings("unchecked")??
  67. ????????????HashMap<String,?Object>?item?=?(HashMap<String,?Object>)?arg0??
  68. ????????????????????.getItemAtPosition(arg2);??
  69. ????????????setTitle((String)?item.get("ItemText"));??
  70. ????????}??
  71. ??
  72. ????}</span>??

后面还会继续介绍如何在Panel加入拖拉效果的处理!

  相关解决方案