android自定义实现抽屉SlidingDrawer的功能
最近项目中需要实现上拉功能,首先想到的就是Android本身自带的抽屉SlidingDrawer,最后也实现了不过,出现的问题就是设置背景色问题,handler和content是两个不同的部分,这就造成图片要做成两部分,从而产生两个部分图片看起来不是一个整体,而且我这个上拉功能,里面要实现一个水平滚动功能,而SlidingDrawer还有其他的限制,同时官方给出api 17以后,这个功能已经废弃,所以自己自定这样一个上拉功能是必须的。
这里我是继承LinearLayout同时实现GestureDetector.OnGestureListener来实现上拉功能。下面是代码:
package com.example.test; import android.content.Context;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.LinearLayout;
import android.widget.RelativeLayout; public class PanelBom extends LinearLayout implements GestureDetector.OnGestureListener{ GestureDetector mGesture = null;
private boolean isScrolling = false;
private int MAX_HEIGHT = 80;//拖动的最大高度,当前布局位于父布局下面-80位置,这个仅仅是调试参数,这个变量是动态设置的。
private float mScrollX; // 滑块滑动距离
public PanelBom(Context context) {
super(context);
init();
}
public PanelBom(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
//初始化一些参数
public void init(){
mGesture = new GestureDetector(this);
mGesture.setIsLongpressEnabled(false);
setBackgroundResource(R.drawable.button_bar);
} @Override
public boolean onTouchEvent(MotionEvent event) {
if (MotionEvent.ACTION_UP == event.getAction() && isScrolling == true) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)getLayoutParams();
// 缩回去
if (layoutParams.bottomMargin < -MAX_HEIGHT / 2) {
new AsynMove().execute(-20);//负--往下
} else {
new AsynMove().execute(20);//正--往上
}
}
return mGesture.onTouchEvent(event);
}
//Touch down时触发
@Override
public boolean onDown(MotionEvent e) {
mScrollX = 0;
isScrolling = false;
// 将之改为true,不然事件不会向下传递.
return true;
}
//Touch了还没有滑动时触发
@Override
public void onShowPress(MotionEvent e) { }
@Override
public boolean onSingleTapUp(MotionEvent e) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
// 说明在上面,要往下
if (layoutParams.bottomMargin >= 0) {
new AsynMove().execute(-20);//负--往下
} else {
new AsynMove().execute(20);//正--往上
}
return true;
}
//Touch了滑动时触发
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
isScrolling = true;
mScrollX += distanceY;
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)getLayoutParams();
layoutParams.bottomMargin += mScrollX;
if (layoutParams.bottomMargin >= 0) {
isScrolling = false;// 拖过头了不需要再执行AsynMove了
layoutParams.bottomMargin = 0;
} else if (layoutParams.bottomMargin <= -MAX_HEIGHT) {
// 拖过头了不需要再执行AsynMove了
isScrolling = false;
layoutParams.bottomMargin = -MAX_HEIGHT;
}
setLayoutParams(layoutParams);
return false;
}
//Touch了不移动一直Touch down时触发
@Override
public void onLongPress(MotionEvent e) { }
//Touch了滑动一点距离后,up时触发。
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
//异步更新布局的位置
class AsynMove extends AsyncTask<Integer, Integer, Void> {
@Override
protected Void doInBackground(Integer... params) {
int times = 0;
int divi = Math.abs(params[0]);
if (MAX_HEIGHT % divi == 0)// 整除
times = MAX_HEIGHT / Math.abs(params[0]);
else
times = MAX_HEIGHT / divi + 1;// 有余数 for (int i = 0; i < times; i++) {
publishProgress(params[0]);
try {
Thread.sleep(divi);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
if (values[0] < 0) {
layoutParams.bottomMargin = Math.max(layoutParams.bottomMargin + values[0], -MAX_HEIGHT);
} else {
layoutParams.bottomMargin = Math.min(layoutParams.bottomMargin + values[0], 0);
}
setLayoutParams(layoutParams); super.onProgressUpdate(values);
}
}
}
主界面:
package com.example.test; import android.app.Activity;
import android.os.Bundle;
import android.widget.RelativeLayout; public class Main5 extends Activity{ RelativeLayout Parent;
PanelBom panelBom;
RelativeLayout.LayoutParams parentParams;
RelativeLayout.LayoutParams paneBomParams;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Parent = new RelativeLayout(getApplicationContext());
panelBom = new PanelBom(getApplicationContext());
parentParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
paneBomParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 150);
paneBomParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
paneBomParams.bottomMargin = -80;
Parent.addView(panelBom, paneBomParams);
setContentView(Parent, parentParams);
} }
实现的效果是:
拖拉,点击实现上拉功能,效果图如下:
android自定义实现抽屉SlidingDrawer的功能的更多相关文章
- Android -- 滑式抽屉SlidingDrawer(非原创)
SlidingDrawer(滑动式抽屉)隐藏屏外的内容,并允许用户拖拽一个handle以显示隐藏的内容.SlidingDrawer可以在垂直或者水平使用.它由两个子视图组成:一个是用户拖拽的handl ...
- android 自定义view之选座功能
效果图: 界面比较粗糙,主要看原理. 这个界面主要包括以下几部分 1.座位 2.左边的排数 3.左上方的缩略图 4.缩略图中的红色区域 5.手指移动时跟随移动 6.两个手指缩放时跟随缩放 主要技术点 ...
- Android控件之SlidingDrawer(滑动式抽屉)详解与实例
SlidingDrawer效果想必大家也见到过,它就是1.5模拟器上进入应用程序列表的效果.下面是截图 一.简介 SlidingDrawer隐藏屏外的内容,并允许用户通过handle以显示隐藏内容.它 ...
- Android抽屉(SlidingDrawer --类似android通知栏下拉效果)
Android抽屉(SlidingDrawer)的实现发 - 红黑联盟http://www.2cto.com/kf/201301/182507.html 可动态布局的Android抽屉之基础http: ...
- (转)[原] Android 自定义View 密码框 例子
遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...
- Android 自定义View合集
自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...
- [原] Android 自定义View步骤
例子如下:Android 自定义View 密码框 例子 1 良好的自定义View 易用,标准,开放. 一个设计良好的自定义view和其他设计良好的类很像.封装了某个具有易用性接口的功能组合,这些功能能 ...
- [原] Android 自定义View 密码框 例子
遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...
- Android 自定义title 之Action Bar
Android 自定义title 之Action Bar 2014-06-29 飞鹰飞龙... 摘自 博客园 阅 10519 转 25 转藏到我的图书馆 微信分享: Action Ba ...
随机推荐
- Python字符串原理剖析------万恶的+号
字符串原理剖析pyc文件,执行python代码时,如果导入了其他的.py文件,那么执行过程中会自动生成一个与其同名的.pyc文件,该文件就是python解释器变异之后产生的字节码 PS:代码经过编译可 ...
- 我的Python成长之路---第二天---Python基础(7)---2016年1月9日(晴)
再说字符串 一.字符串的编码 字符串的编码是个很令人头疼的问题,由于计算机是美国人发明的,他们很理所当然的认为计算机只要能处理127个字母和一些符号就够用了,所以规定了一个字符占用8个比特(bit)也 ...
- 高级UIKit-09(TCPSocket发送文件、上传和下载)
[day1101_SocketSendFile]:发送文件到服务端 发送文件需要在该文件上拼接消息头,比如类型,文件名,文件大小 // 服务端 - (void)viewDidLoad { [super ...
- 用C语言怎么实现复制自己
#include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { char str[80]; ...
- Linux - 输入输出流程序 代码(C)
输入输出流程序 代码(C) 本文地址:http://blog.csdn.net/caroline_wendy 使用输入输出流,控制文件流. STDIN_FILENO,STDOUT_FILENO代表标准 ...
- linux head命令
head 与 tail 就像它的名字一样的浅显易懂,它是用来显示开头或结尾某个数量的文字区块,head 用来显示档案的开头至标准输出中,而 tail 想当然尔就是看档案的结尾. 1.命令格式: hea ...
- this小记
this小记 太久没有研究底层的js相关,今晚差点被紫红爸爸上课了. 正题 var net=new Object(); //定义一个全局变量net net.AjaxRequest=function(u ...
- Java面试题精选(三) JSP/Servlet Java面试逻辑题
-- JSP/Servlet Java面试逻辑题 -- 很显然,Servlet/JSP的WEB前端动态制作的重要性比HTML/CSS/JS的价值高很多,但我们都知道他们都是建立在HT ...
- 极限挑战—C#100万条数据导入SQL SERVER数据库仅用4秒 (附源码)
原文:极限挑战-C#100万条数据导入SQL SERVER数据库仅用4秒 (附源码) 实际工作中有时候需要把大量数据导入数据库,然后用于各种程序计算,本实验将使用5中方法完成这个过程,并详细记录各种方 ...
- 内部框架——axure线框图部件库介绍
网页框架代码<iframe border=0 name=lantk src="要嵌入的网页地址" width=400 height=400 allowTransparency ...