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

于是,我便在网上查询了一下相关的文章,现将这种效果收集了一下,由于文章太多太杂(有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. import project后,出现Unable to get system library for the project

    import project 后,出现Unable to get system library for the project. 这是因为在import 一个项目的时候,没有指定android sdk ...

  2. linux文件属性详解

    Linux 文件或目录的属性主要包括:文件或目录的节点.种类.权限模式.链接数量.所归属的用户和用户组.最近访问或修改的时间等内容.具体情况如下: 命令: ls -lih 输出: [root@loca ...

  3. HDU5649 DZY Loves Sorting 线段树

    题意:BC 76 div1 1004 有中文题面 然后奉上官方题解: 这是一道良心的基础数据结构题. 我们二分a[k]的值,假设当前是mid,然后把大于mid的数字标为1,不大于mid的数字标为0.然 ...

  4. [转]ASP.NET MVC 入门4、Controller与Action

    Controller是MVC中比较重要的一部分.几乎所有的业务逻辑都是在这里进行处理的,并且从Model中取出数据.在ASP.NET MVC Preview5中,将原来的Controller类一分为二 ...

  5. 016专家视图测试脚本开发- Environment对象的使用;Msgbox和Print的区别

    (1)读取Built-in 'file -> settings -> Enrionment -> variable type 为 Built-in os = Environment. ...

  6. 【HTML】Advanced1:Text: Time, Mark, and "Presentational"

    1.Exploring the depths of HTML5 2.</time> <p>Written by Doctor Who on <time datetime= ...

  7. 【笔试】T实习生2014 总结

    2014.4.12 是T的广州站,就在本校,很方便.考前一两天,临时抱佛脚,看着HTMLdog上的网页知识.就算考前,还在懊悔自己为什么不好好利用清明假期,多看点,看多点?哎,哎.. 谁知道一拿到试卷 ...

  8. SSE 标准化向量

    mov esi, this ; vector u movups xmm0, [esi] ; first vector in xmm0 movaps xmm2, xmm0 ; copy original ...

  9. javascript设计模式1

    普通写法 function startAnimation(){ ... } function stopAnimation(){ ... } 对象类 /*Anim class*/ var Anim=fu ...

  10. 《Genesis-3D开源游戏引擎--横版格斗游戏制作教程05:技能读表》

    5.技能读表 技能读表概述: 技能读表,作为实现技能系统更为快捷的一种方式,被广泛应用到游戏开发中.技能配表,作为桥梁连接着游戏策划者和开发者在技能实现上的关系.在游戏技能开发中,开发者只需要根据策划 ...