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

于是,我便在网上查询了一下相关的文章,现将这种效果收集了一下,由于文章太多太杂(有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的实现:

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

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/img3"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.topcsa.demo_drawer1.MainActivity$PlaceholderFragment" > <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:text="滑动外面"
android:textSize="18sp" /> <SlidingDrawer
android:id="@+id/slidingdrawer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:content="@+id/content"
android:handle="@+id/handle"
android:orientation="vertical" > <ImageView
android:id="@id/handle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/img1" >
</ImageView> <LinearLayout
android:id="@id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/img2" > <TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="隐藏的内容" />
</LinearLayout>
</SlidingDrawer> </RelativeLayout>

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

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

         sd.setOnDrawerOpenListener(new OnDrawerOpenListener(){
public void onDrawerOpened() {
// TODO Auto-generated method stub
}
});
sd.setOnDrawerCloseListener(new OnDrawerCloseListener(){
public void onDrawerClosed() {
// TODO Auto-generated method stub
}
});
sd.setOnDrawerScrollListener(new OnDrawerScrollListener(){
public void onScrollEnded() {
// TODO Auto-generated method stub
}
public void onScrollStarted() {
// TODO Auto-generated method stub
}
});

第二种方式DrawerLayout的实现:

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

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".DrawerActivity" > <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" > <!-- The main content view --> <FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" > <Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="open"
/>
</FrameLayout> <!-- The navigation drawer --> <ListView
android:id="@+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout> </RelativeLayout>

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

 private DrawerLayout mDrawerLayout;

     @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); Button button = (Button) findViewById(R.id.btn);
button.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
// 按钮按下,将抽屉打开
mDrawerLayout.openDrawer(Gravity.LEFT); }
}); }

此时,运行代码即可。

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

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

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

main.xml:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:id="@+id/container">
<GridView android:id="@+id/gridview" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:numColumns="auto_fit"
android:verticalSpacing="10dp" android:gravity="center"
android:columnWidth="50dip" android:horizontalSpacing="10dip" />
</LinearLayout>

item.xml:

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:paddingBottom="4dip"
android:layout_width="fill_parent">
<ImageView android:layout_height="wrap_content" android:id="@+id/ItemImage"
android:layout_width="wrap_content" android:layout_centerHorizontal="true">
</ImageView>
<TextView android:layout_width="wrap_content"
android:layout_below="@+id/ItemImage" android:layout_height="wrap_content"
android:text="TextView01" android:layout_centerHorizontal="true"
android:id="@+id/ItemText">
</TextView>
</RelativeLayout>

在默认Activity中:

 public class main extends Activity {
public Panel panel;
public LinearLayout container;
public GridView gridview;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.setTitle("“可动态布局”的抽屉组件之构建基础-----hellogv");
gridview = (GridView) findViewById(R.id.gridview);
container=(LinearLayout)findViewById(R.id.container);
panel=new Panel(this,gridview,200,LayoutParams.FILL_PARENT);
container.addView(panel);//加入Panel控件 //新建测试组件
TextView tvTest=new TextView(this);
tvTest.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
tvTest.setText("测试组件,红字白底");
tvTest.setTextColor(Color.RED);
tvTest.setBackgroundColor(Color.WHITE);
//加入到Panel里面
panel.fillPanelContainer(tvTest); panel.setPanelClosedEvent(panelClosedEvent);
panel.setPanelOpenedEvent(panelOpenedEvent); //往GridView填充测试数据
ArrayList<HashMap<String, Object>> lstImageItem = new ArrayList<HashMap<String, Object>>();
for (int i = 0; i < 100; i++) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("ItemImage", R.drawable.icon);
map.put("ItemText", "NO." + String.valueOf(i));
lstImageItem.add(map);
} SimpleAdapter saImageItems = new SimpleAdapter(this,
lstImageItem,
R.layout.item,
new String[] { "ItemImage", "ItemText" },
new int[] { R.id.ItemImage, R.id.ItemText });
gridview.setAdapter(saImageItems);
gridview.setOnItemClickListener(new ItemClickListener()); } PanelClosedEvent panelClosedEvent =new PanelClosedEvent(){ @Override
public void onPanelClosed(View panel) {
Log.e("panelClosedEvent","panelClosedEvent");
} }; PanelOpenedEvent panelOpenedEvent =new PanelOpenedEvent(){ @Override
public void onPanelOpened(View panel) {
Log.e("panelOpenedEvent","panelOpenedEvent");
} }; class ItemClickListener implements OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> arg0,View arg1, int arg2, long arg3) {
@SuppressWarnings("unchecked")
HashMap<String, Object> item = (HashMap<String, Object>) arg0
.getItemAtPosition(arg2);
setTitle((String) item.get("ItemText"));
} }
}

新建一个Panel类:

 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 &&
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;
} /**
*
* @param v
*/
public void fillPanelContainer(View v)
{
panelContainer.addView(v);
} /**
*
* @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);
}
else if(lp.rightMargin==-(mRightMargin) && panelClosedEvent!=null){
panelClosedEvent.onPanelClosed(Panel.this);
}
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)
new AsynMove().execute(new Integer[] { MOVE_WIDTH });
else if (lp.rightMargin >= 0)
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);
}
else if(lp.rightMargin==-(mRightMargin) && panelClosedEvent!=null){
panelClosedEvent.onPanelClosed(Panel.this);
}
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 抽屉效果的更多相关文章

  1. Android 抽屉效果的导航菜单实现

    Android 抽屉效果的导航菜单实现 抽屉效果的导航菜单 看了很多应用,觉得这种侧滑的抽屉效果的菜单很好. 不用切换到另一个页面,也不用去按菜单的硬件按钮,直接在界面上一个按钮点击,菜单就滑出来,而 ...

  2. Android抽屉效果 DrawerLayout 入门经验总结

    今天试了试这个抽屉布局的效果,结果很崩溃无语 网上很多资料都千篇一律,感觉都有问题,下面总结下几点经验: 先上个效果图: 1.  layout 布局文件中怎么写: <android.suppor ...

  3. android抽屉效果

    所谓抽屉  是区别于侧滑菜单 他不会把内容区域挤掉  他只是覆盖在内容区域 下边一个布局文件  一个代码   可以说的就是布局文件就是 <android.support.v4.widget.Dr ...

  4. Android抽屉(SlidingDrawer --类似android通知栏下拉效果)

    Android抽屉(SlidingDrawer)的实现发 - 红黑联盟http://www.2cto.com/kf/201301/182507.html 可动态布局的Android抽屉之基础http: ...

  5. android: activity之间切换的抽屉效果

    之前一直用的是向左平移和向右平移的切换动画,看到别的APP那个抽屉效果,自己也弄了一个!感谢给我提供帮助的大神们! 将退出动画的参数设置为0时,进入动画则设置为向左平移,就实现了抽屉效果! 进入的动画 ...

  6. Android使用ToolBar+DrawerLayout+NavigationView实现侧滑抽屉效果

    学会使用DrawerLayout 学会使用NavigationView 学会使用ToolBar+DrawerLayout+NavigationView实现侧滑抽屉效果 学会实现Toolbar在顶部以及 ...

  7. 浅谈DrawerLayout(抽屉效果)

    DrawerLayout是V4包下提供的一种左滑右滑抽屉布局效果. 实现效果如下: 因为是官方提供的,所以使用起来也相对的比较简单. DrawerLayout 提供 1.当界面弹出的时候,主要内容区会 ...

  8. 更好的抽屉效果(ios)

    昨天项目基本没啥事了,晚上早早的就回家了,躺在床上无聊地玩着手机(Android的),在清理系统垃圾时被一个“360手机助手”给吸引了, 其实我是被它的那个抽屉效果给吸引了,此时你也许会觉得我out了 ...

  9. android弹力效果菜单、组件化项目、电影票选座控件的源码

    Android精选源码 android启动扫一扫和收付款的小部件源码 android弹力效果的抽屉菜单源码 对RecyclerView Item做动画 源码 android类似QQ空间,微信朋友圈,微 ...

随机推荐

  1. LoadRunner 录制IE 8卡死

    LoadRunner11录制脚本,对IE的版本是有所限制的,它只是支持IE 8 以下版本,其中包括IE 8,高出IE 8版本Loadrunner是不支持的. 我遇到LoadRunner录制脚本时IE8 ...

  2. Restful与webService区别

    有好多人问我们在设计底层服务的时候到底是应该选择目前最流行的RestFul架构还是选择老牌的webService呢?今天我就将这两个概念做一下阐述,到底什么情况下选择什么比较合理. 首先需要了解:RE ...

  3. bss 概念

    BSS段 在采用段式内存管理的架构中,BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS ...

  4. HW3.15

    import java.util.Scanner; public class Solution { public static void main(String[] args) { int lotte ...

  5. HW1.4

    public class Solution { public static void main(String[] args) { System.out.println("a a^2 a^3& ...

  6. arm 交叉编译时 gcc 的 Options

    https://sourceware.org/binutils/docs/as/ARM-Options.html https://gcc.gnu.org/onlinedocs/gcc-4.5.3/gc ...

  7. yii 获取系统级请求参数的常用方法

    1.GET/POST 1.1.获取GET/POST过来的数据 Yii::app()->request->getParam('id'); 1.2.判断数据提交方式 Yii::app()-&g ...

  8. php中的$_SERVER从哪来

    前几个月学了个tcpdump抓包命令,遇到任何问题总想试试,真是程序员的终级武器呀,它像显微镜一下,把任何的丑陋的bug都显示在你的面前. 为什么有题目中所说的疑问呢?因为我发现在不同的环境下面,我获 ...

  9. Linux下OpenSSL 安装

    安装环境:  操作系统:CentOs6.3 OpenSSL Version:openssl-1.0.0e.tar.gz 目前版本最新的SSL地址为http://www.openssl.org/sour ...

  10. @ContextConfiguration注解说明

    @ContextConfiguration Spring整合JUnit4测试时,使用注解引入多个配置文件单个文件 @ContextConfiguration(Locations="../ap ...