• 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

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

    作者:af74776
    文章出处:http://www.cnblogs.com/scetopcsa/
    欢迎关注微信公众号:yilu_yiyou(一路一游),一个不仅仅是代码的世界!
    如果文中有什么错误,欢迎指出。以免更多的人被误导。
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Oracle去除重复(某一列的值重复),取最新(日期字段最新)的一条数据
    eclipse中的项目无法添加到tomcat中
    Myeclipse查看当前项目工作空间
    oracle查看表中否存在某字段,数据库是否存在某张表
    Java中Double原样输出,取消科学计数法
    DateTimeField *** received a naive datetime (***) while time zone support is active
    JS 将UTC时间转为本地时间
    Python与Django的时区问题
    在Django / DRF中正确处理日期时间/时区
    django时间的时区问题
  • 原文地址:https://www.cnblogs.com/scetopcsa/p/3675488.html
Copyright © 2020-2023  润新知