Android 抽屉效果
昨天在用“酷我音乐”听歌的时候注意到了界面右上角的四角方块,当我点击这个方块的时候会从屏幕的左边弹出新的界面而把原来的界面挤到左边,是显示了一小部分。
于是,我便在网上查询了一下相关的文章,现将这种效果收集了一下,由于文章太多太杂(有CSDN、博客园、开源中国等)我就不具体指明了。如有侵权敬请谅解。
要实现抽屉效果,有两种方式:
- 使用大家熟知的滑动抽屉类SlidingDrawer。http://developer.android.com/reference/android/widget/SlidingDrawer.html
- 使用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 抽屉效果的更多相关文章
- Android 抽屉效果的导航菜单实现
Android 抽屉效果的导航菜单实现 抽屉效果的导航菜单 看了很多应用,觉得这种侧滑的抽屉效果的菜单很好. 不用切换到另一个页面,也不用去按菜单的硬件按钮,直接在界面上一个按钮点击,菜单就滑出来,而 ...
- Android抽屉效果 DrawerLayout 入门经验总结
今天试了试这个抽屉布局的效果,结果很崩溃无语 网上很多资料都千篇一律,感觉都有问题,下面总结下几点经验: 先上个效果图: 1. layout 布局文件中怎么写: <android.suppor ...
- android抽屉效果
所谓抽屉 是区别于侧滑菜单 他不会把内容区域挤掉 他只是覆盖在内容区域 下边一个布局文件 一个代码 可以说的就是布局文件就是 <android.support.v4.widget.Dr ...
- Android抽屉(SlidingDrawer --类似android通知栏下拉效果)
Android抽屉(SlidingDrawer)的实现发 - 红黑联盟http://www.2cto.com/kf/201301/182507.html 可动态布局的Android抽屉之基础http: ...
- android: activity之间切换的抽屉效果
之前一直用的是向左平移和向右平移的切换动画,看到别的APP那个抽屉效果,自己也弄了一个!感谢给我提供帮助的大神们! 将退出动画的参数设置为0时,进入动画则设置为向左平移,就实现了抽屉效果! 进入的动画 ...
- Android使用ToolBar+DrawerLayout+NavigationView实现侧滑抽屉效果
学会使用DrawerLayout 学会使用NavigationView 学会使用ToolBar+DrawerLayout+NavigationView实现侧滑抽屉效果 学会实现Toolbar在顶部以及 ...
- 浅谈DrawerLayout(抽屉效果)
DrawerLayout是V4包下提供的一种左滑右滑抽屉布局效果. 实现效果如下: 因为是官方提供的,所以使用起来也相对的比较简单. DrawerLayout 提供 1.当界面弹出的时候,主要内容区会 ...
- 更好的抽屉效果(ios)
昨天项目基本没啥事了,晚上早早的就回家了,躺在床上无聊地玩着手机(Android的),在清理系统垃圾时被一个“360手机助手”给吸引了, 其实我是被它的那个抽屉效果给吸引了,此时你也许会觉得我out了 ...
- android弹力效果菜单、组件化项目、电影票选座控件的源码
Android精选源码 android启动扫一扫和收付款的小部件源码 android弹力效果的抽屉菜单源码 对RecyclerView Item做动画 源码 android类似QQ空间,微信朋友圈,微 ...
随机推荐
- C# using Sendkey function to send a key to another application
If notepad is already started, you should write: // import the function in your class [DllImport (&q ...
- HDOJ-ACM1021(JAVA)
题意: 斐波拉契数列的另外一个变型,如果F(n)能被3整除,则输出yes,否则输出no.(n<1000000) 解题思路: 看到(n<1000000)这个条件,有点感觉递归量有点大,因此要 ...
- POJ1006 - Biorhythms(中国剩余定理)
题目大意 略...有中文... 题解 就是解同余方程组 x≡(p-d)(mod 23) x≡(e-d)(mod 28) x≡(i-d)(mod 33) 最简单的中国剩余定理应用.... 代码: #in ...
- C++中字符串的结尾标志\0
\0是C++中字符串的结尾标志,存储在字符串的结尾,它虽然不计入串长,但要占一个字节的内存空间.在百度百科中查看\0词条,会有这样一句话:c/c++中规定字符串的结尾标志为'\0'.有人可能认为,在C ...
- iOS绘图教程 (转,拷贝以记录)
本文是<Programming iOS5>中Drawing一章的翻译,考虑到主题完整性,在翻译过程中我加入了一些书中没有涉及到的内容.希望本文能够对你有所帮助. 转自:http://www ...
- 怎样做出通用的pos小票打印程序
POS小票打印机分为热敏和针式俩种. 打印纸的宽度分为58毫米.76毫米和80毫米三种. 打印接口分为:串口.并口.USB和网口(以太网). 热敏打印机速度较快,打印的时候噪音少,针打可以使用多联纸自 ...
- 为Android安装BusyBox
大家是否有过这样的经历,在命令行里输入adb shell,然后使用命令操作你的手机或模拟器,但是那些命令都是常见Linux命令的阉割缩水版,用起来很不爽.是否想过在 Android上使用较完整的she ...
- Android完美解决输入框EditText隐藏密码打勾显示密码问题
长话短说,一共有两种方法.首先你需要在布局文件里面给EditText设置一个android:inputType="numberPassword"属性.我这里默认规定密码只能是数字了 ...
- 自己修改select的样式(修改select右边的小三角)
CSS就可以解决,原理是将浏览器默认的下拉框样式清除,然后应用上自己的,再附一张向右对齐小箭头的图片即可. select { /*Chrome和Firefox里面的边框是不一样的,所以复写了一下*/ ...
- iOS不勾选设置,实现某个界面强制横屏
1.在不勾选横屏的前提下,实现某一个界面横屏显示,比如播放视频.图表显示等. 2.只能Present跳转,Push会无效. 3.实现代码 在需要横屏的VC里,添加如下代码 #pragma mark 强 ...