Android控件拖动的实现
2016-03-31 12:10
423 查看
转自:http://blog.csdn.net/wangjia55/article/details/7458620,还可以参考如下网址了解getx
等方法区别:http://blog.csdn.net/jason0539/article/details/42743531,写的实在太好,所以就转载了,感谢这些前辈:
标签: androidjavabuttonactionlayoutxml
2012-04-13 17:03 8826人阅读 评论(7) 收藏 举报
分类:
android UI设计(54)
这个也是从网上得到的代码,例子比较简单,但是如果有需要此功能的,这个例子可以提供很多提示,首先,给个截图
这个是拖动以后的效果,一个imageview和一个button控件,提供两份代码下载吧,一份是只有一个Button的,另一份就是像上图,就是多了一个imagview!先看下代码吧,比较简单:
[java] view plaincopy
public class DraftTest extends Activity implements OnTouchListener{
/** Called when the activity is first created. */
int screenWidth;
int screenHeight;
int lastX;
int lastY;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DisplayMetrics dm = getResources().getDisplayMetrics();
screenWidth = dm.widthPixels;
screenHeight = dm.heightPixels - 50;
Button button=(Button)findViewById(R.id.btn);
ImageView imageView=(ImageView)findViewById(R.id.btn2);
imageView.setOnTouchListener(this);
button.setOnTouchListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
int action=event.getAction();
Log.i("@@@@@@", "Touch:"+action);
//Toast.makeText(DraftTest.this, "λ�ã�"+x+","+y, Toast.LENGTH_SHORT).show();
switch(action){
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
/**
* layout(l,t,r,b)
* l Left position, relative to parent
t Top position, relative to parent
r Right position, relative to parent
b Bottom position, relative to parent
* */
case MotionEvent.ACTION_MOVE:
int dx =(int)event.getRawX() - lastX;
int dy =(int)event.getRawY() - lastY;
int left = v.getLeft() + dx;
int top = v.getTop() + dy;
int right = v.getRight() + dx;
int bottom = v.getBottom() + dy;
if(left < 0){
left = 0;
right = left + v.getWidth();
}
if(right > screenWidth){
right = screenWidth;
left = right - v.getWidth();
}
if(top < 0){
top = 0;
bottom = top + v.getHeight();
}
if(bottom > screenHeight){
bottom = screenHeight;
top = bottom - v.getHeight();
}
v.layout(left, top, right, bottom);
Log.i("@@@@@@", "position��" + left +", " + top + ", " + right + ", " + bottom);
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
case MotionEvent.ACTION_UP:
break;
}
return false;
}
}
高度减去50是减去状态栏和标题栏的高度。
[java] view plaincopy
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
然后获取控件一开始的位置,然后在ACTION_MOVIE中:
[java] view plaincopy
int dx =(int)event.getRawX() - lastX;
int dy =(int)event.getRawY() - lastY;
int left = v.getLeft() + dx;
int top = v.getTop() + dy;
int right = v.getRight() + dx;
int bottom = v.getBottom() + dy;
if(left < 0){
left = 0;
right = left + v.getWidth();
}
if(right > screenWidth){
right = screenWidth;
left = right - v.getWidth();
}
if(top < 0){
top = 0;
bottom = top + v.getHeight();
}
if(bottom > screenHeight){
bottom = screenHeight;
top = bottom - v.getHeight();
}
v.layout(left, top, right, bottom);
Log.i("@@@@@@", "position��" + left +", " + top + ", " + right + ", " + bottom);
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
getLeft()方法得到的是控件左边坐标距离父控件原点(左上角,坐标(0,0))的y轴距离,getRight()是控件右边距离父控件原点的y轴距离,同理,getTop和getButtom是距离的x轴距离。
[java] view plaincopy
if(left < 0){
left = 0;
right = left + v.getWidth();
}
if(right > screenWidth){
right = screenWidth;
left = right - v.getWidth();
}
if(top < 0){
top = 0;
bottom = top + v.getHeight();
}
if(bottom > screenHeight){
bottom = screenHeight;
top = bottom - v.getHeight();
}
这里的判断是为了是控件不超出屏幕以外,即:到达边界以后,不能再移动。
[java] view plaincopy
v.layout(left, top, right, bottom);
设置View的位置。
有一点忘记说了,就是像ImageView和TextView这些控件,要想实现拖动,要在xml文件中设置它的clickable为true。
[java] view plaincopy
android:clickable="true"
就这样,这些就是这个demo的全部内容。
最后,是代码的下载地址:
http://download.csdn.net/detail/aomandeshangxiao/4187376, http://download.csdn.net/detail/aomandeshangxiao/4189910
========================分割线2016年4月19日10:12:02================================================
当界面如果有切换、或者刷新的动作之后,发现所有拖动的控件,都会恢复到原来的位置,应该是父类执行了onlayout方法,恢复到默认的位置了,需要重新复写父类的方法,如下:
这个更简单,在刷新子控件位置的时候,去遍历一下,找到DraggableFloatingButton,如果left不为-1则说明之前移动过了,子控件再自己调次layout用自己记录的上次移动后的坐标,即可保证位置在父布局刷新的时候不受影响
父类重写的代码如下:
上述方法没有试验成功,刚界面有更新,拖动的控件会重新恢复到原来的位置,还是使用layoutparams参数,如下:
等方法区别:http://blog.csdn.net/jason0539/article/details/42743531,写的实在太好,所以就转载了,感谢这些前辈:
Android控件拖动的实现
标签: androidjavabuttonactionlayoutxml2012-04-13 17:03 8826人阅读 评论(7) 收藏 举报
分类:
android UI设计(54)
这个也是从网上得到的代码,例子比较简单,但是如果有需要此功能的,这个例子可以提供很多提示,首先,给个截图
这个是拖动以后的效果,一个imageview和一个button控件,提供两份代码下载吧,一份是只有一个Button的,另一份就是像上图,就是多了一个imagview!先看下代码吧,比较简单:
[java] view plaincopy
public class DraftTest extends Activity implements OnTouchListener{
/** Called when the activity is first created. */
int screenWidth;
int screenHeight;
int lastX;
int lastY;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DisplayMetrics dm = getResources().getDisplayMetrics();
screenWidth = dm.widthPixels;
screenHeight = dm.heightPixels - 50;
Button button=(Button)findViewById(R.id.btn);
ImageView imageView=(ImageView)findViewById(R.id.btn2);
imageView.setOnTouchListener(this);
button.setOnTouchListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
int action=event.getAction();
Log.i("@@@@@@", "Touch:"+action);
//Toast.makeText(DraftTest.this, "λ�ã�"+x+","+y, Toast.LENGTH_SHORT).show();
switch(action){
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
/**
* layout(l,t,r,b)
* l Left position, relative to parent
t Top position, relative to parent
r Right position, relative to parent
b Bottom position, relative to parent
* */
case MotionEvent.ACTION_MOVE:
int dx =(int)event.getRawX() - lastX;
int dy =(int)event.getRawY() - lastY;
int left = v.getLeft() + dx;
int top = v.getTop() + dy;
int right = v.getRight() + dx;
int bottom = v.getBottom() + dy;
if(left < 0){
left = 0;
right = left + v.getWidth();
}
if(right > screenWidth){
right = screenWidth;
left = right - v.getWidth();
}
if(top < 0){
top = 0;
bottom = top + v.getHeight();
}
if(bottom > screenHeight){
bottom = screenHeight;
top = bottom - v.getHeight();
}
v.layout(left, top, right, bottom);
Log.i("@@@@@@", "position��" + left +", " + top + ", " + right + ", " + bottom);
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
case MotionEvent.ACTION_UP:
break;
}
return false;
}
}
高度减去50是减去状态栏和标题栏的高度。
[java] view plaincopy
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
然后获取控件一开始的位置,然后在ACTION_MOVIE中:
[java] view plaincopy
int dx =(int)event.getRawX() - lastX;
int dy =(int)event.getRawY() - lastY;
int left = v.getLeft() + dx;
int top = v.getTop() + dy;
int right = v.getRight() + dx;
int bottom = v.getBottom() + dy;
if(left < 0){
left = 0;
right = left + v.getWidth();
}
if(right > screenWidth){
right = screenWidth;
left = right - v.getWidth();
}
if(top < 0){
top = 0;
bottom = top + v.getHeight();
}
if(bottom > screenHeight){
bottom = screenHeight;
top = bottom - v.getHeight();
}
v.layout(left, top, right, bottom);
Log.i("@@@@@@", "position��" + left +", " + top + ", " + right + ", " + bottom);
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
getLeft()方法得到的是控件左边坐标距离父控件原点(左上角,坐标(0,0))的y轴距离,getRight()是控件右边距离父控件原点的y轴距离,同理,getTop和getButtom是距离的x轴距离。
[java] view plaincopy
if(left < 0){
left = 0;
right = left + v.getWidth();
}
if(right > screenWidth){
right = screenWidth;
left = right - v.getWidth();
}
if(top < 0){
top = 0;
bottom = top + v.getHeight();
}
if(bottom > screenHeight){
bottom = screenHeight;
top = bottom - v.getHeight();
}
这里的判断是为了是控件不超出屏幕以外,即:到达边界以后,不能再移动。
[java] view plaincopy
v.layout(left, top, right, bottom);
设置View的位置。
有一点忘记说了,就是像ImageView和TextView这些控件,要想实现拖动,要在xml文件中设置它的clickable为true。
[java] view plaincopy
android:clickable="true"
就这样,这些就是这个demo的全部内容。
最后,是代码的下载地址:
http://download.csdn.net/detail/aomandeshangxiao/4187376, http://download.csdn.net/detail/aomandeshangxiao/4189910
========================分割线2016年4月19日10:12:02================================================
当界面如果有切换、或者刷新的动作之后,发现所有拖动的控件,都会恢复到原来的位置,应该是父类执行了onlayout方法,恢复到默认的位置了,需要重新复写父类的方法,如下:
这个更简单,在刷新子控件位置的时候,去遍历一下,找到DraggableFloatingButton,如果left不为-1则说明之前移动过了,子控件再自己调次layout用自己记录的上次移动后的坐标,即可保证位置在父布局刷新的时候不受影响
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); for (int i = 0; i < getChildCount(); i++) { if (getChildAt(i) instanceof DraggableFloatingButton) { // 为了防止浮动按钮恢复原位,布局子控件位置时使用上次记录的位置 DraggableFloatingButton child = (DraggableFloatingButton) getChildAt(i); if (child.getLastLeft() != -1) { child.layout(child.getLastLeft(), child.getLastTop(), child.getLastRight(), child.getLastBottom()); } break; } } }
父类重写的代码如下:
package net.loonggg.viewgroup; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; public class MyViewGroup extends ViewGroup { public MyViewGroup(Context context) { super(context); } public MyViewGroup(Context context, AttributeSet attrs) { super(context, attrs); } public MyViewGroup(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * 计算控件的大小 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int measureWidth = measureWidth(widthMeasureSpec); int measureHeight = measureHeight(heightMeasureSpec); // 计算自定义的ViewGroup中所有子控件的大小 measureChildren(widthMeasureSpec, heightMeasureSpec); // 设置自定义的控件MyViewGroup的大小 setMeasuredDimension(measureWidth, measureHeight); } private int measureWidth(int pWidthMeasureSpec) { int result = 0; int widthMode = MeasureSpec.getMode(pWidthMeasureSpec);// 得到模式 int widthSize = MeasureSpec.getSize(pWidthMeasureSpec);// 得到尺寸 switch (widthMode) { /** * mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY, * MeasureSpec.AT_MOST。 * * * MeasureSpec.EXACTLY是精确尺寸, * 当我们将控件的layout_width或layout_height指定为具体数值时如andorid * :layout_width="50dip",或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。 * * * MeasureSpec.AT_MOST是最大尺寸, * 当控件的layout_width或layout_height指定为WRAP_CONTENT时 * ,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可 * 。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。 * * * MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView, * 通过measure方法传入的模式。 */ case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = widthSize; break; } return result; } private int measureHeight(int pHeightMeasureSpec) { int result = 0; int heightMode = MeasureSpec.getMode(pHeightMeasureSpec); int heightSize = MeasureSpec.getSize(pHeightMeasureSpec); switch (heightMode) { case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = heightSize; break; } return result; } /** * 覆写onLayout,其目的是为了指定视图的显示位置,方法执行的前后顺序是在onMeasure之后,因为视图肯定是只有知道大小的情况下, * 才能确定怎么摆放 */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // 记录总高度 int mTotalHeight = 0; // 遍历所有子视图 int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); // 获取在onMeasure中计算的视图尺寸 int measureHeight = childView.getMeasuredHeight(); int measuredWidth = childView.getMeasuredWidth(); childView.layout(l, mTotalHeight, measuredWidth, mTotalHeight + measureHeight); mTotalHeight += measureHeight; } } }//==============================分割线,2016年4月25日13:59:05=================================
上述方法没有试验成功,刚界面有更新,拖动的控件会重新恢复到原来的位置,还是使用layoutparams参数,如下:
/** * 监听左上方悬浮的控件 */ @Override public boolean onTouch(View v, MotionEvent event) { if (DocCaptain.getInstance().isIfOrderLayout()) { webviewWidth = DocCaptain.getInstance().getWebviewWidthTrade(); webviewHeight = DocCaptain.getInstance().getWebviewHeightTrade(); } int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); break; case MotionEvent.ACTION_UP: break; case MotionEvent.ACTION_POINTER_DOWN: break; case MotionEvent.ACTION_POINTER_UP: break; case MotionEvent.ACTION_MOVE: int dx = (int) event.getRawX() - lastX; int dy = (int) event.getRawY() - lastY; int left = v.getLeft() + dx; int top = v.getTop() + dy; int right = v.getRight() + dx; int bottom = v.getBottom() + dy; if (left < 0) { left = 0; right = left + v.getWidth(); } if (right > webviewWidth) { right = webviewWidth; left = right - v.getWidth(); } if (top < 0) { top = 0; bottom = top + v.getHeight(); } if (bottom > webviewHeight) { bottom = webviewHeight; top = bottom - v.getHeight(); } RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) v .getLayoutParams(); layoutParams.leftMargin = left; layoutParams.topMargin = top; layoutParams.rightMargin = right; layoutParams.bottomMargin = bottom; v.setLayoutParams(layoutParams); // // DocCaptain.getInstance().setSuspendLeft(left); // DocCaptain.getInstance().setSuspendTop(top); // DocCaptain.getInstance().setSuspendRight(right); // DocCaptain.getInstance().setSuspendBottom(bottom); // v.layout(left, top, right, bottom); lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); break; } v.invalidate(); return true; }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories