Android 抽屉效果

昨天在用“酷我音乐”听歌的时候注意到了界面右上角的四角方块,当我点击这个方块的时候会从屏幕的左边弹出新的界面而把原来的界面挤到左边,是显示了一小部分。

于是,我便在网上查询了一下相关的文章,现将这种效果收集了一下,由于文章太多太杂(有CSDN、博客园、开源中国等)我就不具体指明了。如有侵权敬请谅解。

 

要实现抽屉效果,有两种方式:

  1. 使用大家熟知的滑动抽屉类SlidingDrawer。http://developer.android.com/reference/android/widget/SlidingDrawer.html
  2. 使用DrawerLayout。http://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html

下面我们分别用这两种方式来实现这个效果:

第一种方式SlidingDrawer的实现:

仅需要实现布局文件就能看到简单的效果:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

 2     xmlns:tools="http://schemas.android.com/tools"

 3     android:layout_width="match_parent"

 4     android:layout_height="match_parent"

 5     android:background="@drawable/img3"

 6     android:paddingBottom="@dimen/activity_vertical_margin"

 7     android:paddingLeft="@dimen/activity_horizontal_margin"

 8     android:paddingRight="@dimen/activity_horizontal_margin"

 9     android:paddingTop="@dimen/activity_vertical_margin"

10     tools:context="com.topcsa.demo_drawer1.MainActivity$PlaceholderFragment" >

11 

12     <TextView

13         android:layout_width="match_parent"

14         android:layout_height="wrap_content"

15         android:gravity="center_vertical|center_horizontal"

16         android:text="滑动外面"

17         android:textSize="18sp" />

18 

19     <SlidingDrawer

20         android:id="@+id/slidingdrawer"

21         android:layout_width="match_parent"

22         android:layout_height="wrap_content"

23         android:content="@+id/content"

24         android:handle="@+id/handle"

25         android:orientation="vertical" >

26 

27         <ImageView

28             android:id="@id/handle"

29             android:layout_width="wrap_content"

30             android:layout_height="wrap_content"

31             android:src="@drawable/img1" >

32         </ImageView>

33 

34         <LinearLayout

35             android:id="@id/content"

36             android:layout_width="match_parent"

37             android:layout_height="match_parent"

38             android:background="@drawable/img2" >

39 

40             <TextView

41                 android:layout_width="match_parent"

42                 android:layout_height="match_parent"

43                 android:text="隐藏的内容" />

44         </LinearLayout>

45     </SlidingDrawer>

46 

47 </RelativeLayout>
View Code

此时运行程序就可以看到简单的抽屉效果,此外SlidingDrawer还提供了一些方法:

 1 <span style="white-space: pre;">    </span>SlidingDrawer sd = (SlidingDrawer)findViewById(R.id.slidingdrawer);  

 2           

 3         sd.setOnDrawerOpenListener(new OnDrawerOpenListener(){  

 4             public void onDrawerOpened() {  

 5                 // TODO Auto-generated method stub  

 6             }  

 7         });  

 8         sd.setOnDrawerCloseListener(new OnDrawerCloseListener(){  

 9             public void onDrawerClosed() {  

10                 // TODO Auto-generated method stub  

11             }  

12         });  

13         sd.setOnDrawerScrollListener(new OnDrawerScrollListener(){  

14             public void onScrollEnded() {  

15                 // TODO Auto-generated method stub  

16             }  

17             public void onScrollStarted() {  

18                 // TODO Auto-generated method stub  

19             }     

20         });
View Code

 

第二种方式DrawerLayout的实现:

我们首先还是来实现布局文件main.xml:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

 2     xmlns:tools="http://schemas.android.com/tools"

 3     android:layout_width="match_parent"

 4     android:layout_height="match_parent"

 5     android:paddingBottom="@dimen/activity_vertical_margin"

 6     android:paddingLeft="@dimen/activity_horizontal_margin"

 7     android:paddingRight="@dimen/activity_horizontal_margin"

 8     android:paddingTop="@dimen/activity_vertical_margin"

 9     tools:context=".DrawerActivity" >

10 

11     <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"

12         android:id="@+id/drawer_layout"

13         android:layout_width="match_parent"

14         android:layout_height="match_parent" >

15 

16         <!-- The main content view -->

17 

18         <FrameLayout

19             android:id="@+id/content_frame"

20             android:layout_width="match_parent"

21             android:layout_height="match_parent" >

22 

23             <Button

24                 android:id="@+id/btn"

25                 android:layout_width="match_parent"

26                 android:layout_height="wrap_content"

27                 android:text="open" 

28                 />

29         </FrameLayout>

30 

31         <!-- The navigation drawer -->

32         

33         <ListView

34             android:id="@+id/left_drawer"

35             android:layout_width="240dp"

36             android:layout_height="match_parent"

37             android:layout_gravity="start"

38             android:background="#111"

39             android:choiceMode="singleChoice"

40             android:divider="@android:color/transparent"

41             android:dividerHeight="0dp" />

42     </android.support.v4.widget.DrawerLayout>

43 

44 </RelativeLayout>
View Code

然后我们修改MainActivity中的代码:

 1 private DrawerLayout mDrawerLayout;

 2 

 3     @Override

 4     protected void onCreate(Bundle savedInstanceState) {

 5         super.onCreate(savedInstanceState);

 6         setContentView(R.layout.main);

 7         mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

 8 

 9         Button button = (Button) findViewById(R.id.btn);

10         button.setOnClickListener(new OnClickListener() {

11 

12             @Override

13             public void onClick(View v) {

14                 // 按钮按下,将抽屉打开

15                 mDrawerLayout.openDrawer(Gravity.LEFT);

16 

17             }

18         });

19 

20     }
View Code

此时,运行代码即可。

大家需要在“抽屉”中放些什么东西,自己在布局文件和java代码中添加或修改就行了。

 

此外,我再附加些抽屉效果,个人感觉还不错:

两个布局文件main.xml和item.xml分别为:

main.xml:

1 <?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>
View Code

item.xml:

 1 <?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>  
View Code

在默认Activity中:

 1 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     }

73 }
View Code

新建一个Panel类:

  1 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 && 

 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      * 

 97      * @param v

 98      */

 99     public void fillPanelContainer(View v)

100     {

101         panelContainer.addView(v);

102     }

103     

104     /**

105      * 

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);

142             }

143             else if(lp.rightMargin==-(mRightMargin) && panelClosedEvent!=null){

144                 panelClosedEvent.onPanelClosed(Panel.this);

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)

161             new AsynMove().execute(new Integer[] { MOVE_WIDTH });

162         else if (lp.rightMargin >= 0)

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);

186         }

187         else if(lp.rightMargin==-(mRightMargin) && panelClosedEvent!=null){

188             panelClosedEvent.onPanelClosed(Panel.this);

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 }
View Code

此时就可以运行这个例子了。

你可能感兴趣的:(android)