自定义可拖拽的容器LinearLayout2
2015-11-26 22:22
295 查看
之前的一篇文章“自定义可拖拽的LinearLayout”是监听手势事件,使用layout(),改变整个容器的内容,
但是想了想,改变整个容器的位置不太好,所以今天使用scrollTo,scroBy,通过改变容器里的内容的位置来实现拖拽。
下面附上代码
一.重写onTouchEvent函数,其实就是将上篇的layout(getLeft()+dx,getTop()+dy,getRight()+dx,getBottom()+dy)
改成了scrollBy((int)(-dx)(int)(-dy))
二.
但是这样有个不好的地方就是内容可以不限制向某一个方向拖拽直至消失,用户体验不好,
为了更好的体现,实现一个回拉的效果
这里使用增加一个判断
但是由出现了一个问题,scrollBy是瞬间是容器的内容移动到某个位置,为了得到更好的用户体验,使用Scoller达到平滑移动的效果
}
重写容器的computeScoll方法
好了达到了回拉的效果。
但是发现不论往哪个方向过度拖拽都会回到中心,这样也不太好所以添加如下代码,
如果想右过度拖拽,则内容回拉到左边
如果向左过度拖拽,则内容回拉到右边
如果想下过度拖拽,则内容回拉到底部
完整代码如下
关于scollTo,scrollBy,Scoller.以及android的坐标问题将在下篇讲到
但是想了想,改变整个容器的位置不太好,所以今天使用scrollTo,scroBy,通过改变容器里的内容的位置来实现拖拽。
下面附上代码
一.重写onTouchEvent函数,其实就是将上篇的layout(getLeft()+dx,getTop()+dy,getRight()+dx,getBottom()+dy)
改成了scrollBy((int)(-dx)(int)(-dy))
case MotionEvent.ACTION_MOVE: { // Find the index of the active pointer and fetch its position final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); final float x = MotionEventCompat.getX(ev, pointerIndex); final float y = MotionEventCompat.getY(ev, pointerIndex); // Calculate the distance moved final float dx = x - mLastTouchX; final float dy = y - mLastTouchY; scrollBy((int) (-dx), (int) (-dy)); invalidate(); mLastTouchX = x; mLastTouchY = y; break; }
二.
但是这样有个不好的地方就是内容可以不限制向某一个方向拖拽直至消失,用户体验不好,
为了更好的体现,实现一个回拉的效果
这里使用增加一个判断
//获取子视图 LinearLayout view = (LinearLayout) getChildAt(0); if (view == null) { return true; } //获取子视图中心点 int[] arrs = new int[2]; view.getLocationOnScreen(arrs); int viewX = arrs[0]; int viewY = arrs[1]; int centerX = ((viewX + view.getWidth()) + viewX) / 2; int centerY = ((viewY + view.getHeight()) + viewY) / 2; Log.i("viewX,viewY", "" + viewX + " " + centerY); Log.i("getWidth(),getHeight", "" + getWidth() + " " + getHeight()); Log.i("xx", "" + centerX + " " + centerY); //如果子视图的中心超过了屏幕的可见区域则视图回到原来的位置,getScrollX是视图在x轴上平移的距离和 if(centerX<=getLeft()||centerX>getRight()||centerY>getBottom()||centerY<getTop()){ scrollBy(-getScrollX(),-getScrollY()); }
但是由出现了一个问题,scrollBy是瞬间是容器的内容移动到某个位置,为了得到更好的用户体验,使用Scoller达到平滑移动的效果
//如果子视图的中心超过了屏幕的可见区域则视图回到原来的位置,getScrollX是视图在x轴上平移的距离和 if(centerX<=getLeft()||centerX>getRight()||centerY>getBottom()||centerY<getTop()){
mScroller.startScroll(getScrollX(), getScrollY(), -getScrollX(), -getScrollY());
}
重写容器的computeScoll方法
@Override public void computeScroll() { super.computeScroll(); if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } }
好了达到了回拉的效果。
但是发现不论往哪个方向过度拖拽都会回到中心,这样也不太好所以添加如下代码,
如果想右过度拖拽,则内容回拉到左边
如果向左过度拖拽,则内容回拉到右边
如果想下过度拖拽,则内容回拉到底部
if (centerY <= getTop() && centerX > getLeft()) {//显示下边 mScroller.startScroll(getScrollX(), getScrollY(), 0, (view.getHeight() - getHeight()) - getScrollY()); invalidate(); return true; } if (centerX <= getLeft() || centerY <= getTop()) {//显示右边 mScroller.startScroll(getScrollX(), getScrollY(), (view.getWidth() - getWidth()) - getScrollX(), -getScrollY()); invalidate(); return true; } if (centerX >= getRight() || centerY >= getBottom()) {//显示左边 mScroller.startScroll(getScrollX(), getScrollY(), -getScrollX(), -getScrollY()); invalidate(); return true; }
完整代码如下
package com.beidouapp.ilink.demoapp.widget;
import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
import android.widget.Scroller;
import com.beidouapp.ilink.demoapp.utiles.Util;
/**
* Created by xyb on 2015/11/25.
*/
public class GoogleDragDemo extends LinearLayout {
private float mLastTouchX;
private float mLastTouchY;
private Scroller mScroller;
public GoogleDragDemo(Context context) {
super(context);
}
public GoogleDragDemo(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
mScroller = new Scroller(context);
}
// The ‘active pointer’ is the one currently moving our object.
private int INVALID_POINTER_ID = -1000;
private int mActivePointerId = INVALID_POINTER_ID;
@Override public void computeScroll() { super.computeScroll(); if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } }
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
//为了使手指按在Button等可点击的控件上任可以滑动,需要拦截滑动实践
//并且为了使坐标准确,在此处记录按下的点
switch (action) {
case MotionEvent.ACTION_MOVE:
return true;
case MotionEvent.ACTION_DOWN:
final int pointerIndex = MotionEventCompat.getActionIndex(event);
mActivePointerId = MotionEventCompat.getPointerId(event, pointerIndex);
final float x = MotionEventCompat.getX(event, pointerIndex);
final float y = MotionEventCompat.getY(event, pointerIndex);
// Remember where we started (for dragging)
mLastTouchX = x;
mLastTouchY = y;
// Save the ID of this pointer (for dragging)
mActivePointerId = MotionEventCompat.getPointerId(event, 0);
mActivePointerId = MotionEventCompat.getPointerId(event, 0);
return false;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
// mScaleDetector.onTouchEvent(ev);
final int action = MotionEventCompat.getActionMasked(ev);
switch (action) {
case MotionEvent.ACTION_DOWN: {
break;
}
case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
final int pointerIndex =
MotionEventCompat.findPointerIndex(ev, mActivePointerId);
final float x = MotionEventCompat.getX(ev, pointerIndex);
final float y = MotionEventCompat.getY(ev, pointerIndex);
// Calculate the distance moved
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
if(getChildCount()!=1){
Log.e("错误","只能有一个视图");
return true;
}
//获取子视图
LinearLayout view = (LinearLayout) getChildAt(0);
//获取子视图中心点
int[] arrs = new int[2];
view.getLocationOnScreen(arrs);
int viewX = arrs[0];
int viewY = arrs[1];
int centerX = ((viewX + view.getWidth()) + viewX) / 2;
int centerY = ((viewY + view.getHeight()) + viewY) / 2;
Log.i("viewX,viewY", "" + viewX + " " + centerY);
Log.i("getWidth(),getHeight", "" + getWidth() + " " + getHeight());
Log.i("xx", "" + centerX + " " + centerY);
if (centerY <= getTop() && centerX > getLeft()) {//显示下边
mScroller.startScroll(getScrollX(), getScrollY(), 0, (view.getHeight() - getHeight()) - getScrollY());
invalidate();
return true;
}
if (centerX <= getLeft() || centerY <= getTop()) {//显示右边
mScroller.startScroll(getScrollX(), getScrollY(), (view.getWidth() - getWidth) - getScrollX(), -getScrollY());
invalidate();
return true;
}
if (centerX >= getRight() || centerY >= getBottom()) {//显示左边
mScroller.startScroll(getScrollX(), getScrollY(), -getScrollX(), -getScrollY());
invalidate();
return true;
}
scrollBy((int) (-dx), (int) (-dy));
invalidate();
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);
mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);
mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
}
break;
}
}
return true;
}
}
关于scollTo,scrollBy,Scoller.以及android的坐标问题将在下篇讲到
相关文章推荐
- AndroidManifest.xml文件解析
- Android:MediaPlayer播放音频
- Android的一个登录小实例
- Android开发中Android数据的四种存储方式
- Android中的BLE
- Android-loader
- android113 自定义进度条
- Android内存和进程的关系
- Android Paint和Canvas常用方法和效果
- android事件处理机制
- 提升工作效率的几个Android Studio插件和工具
- 发布模式编译android签名
- [转]Android Shape渲染的使用(经典,学习研究不后悔)
- 模拟飞翔的小鸟android版 文档二
- Android学习之解决ListView中item点击事件和item中Button点击事件冲突问题
- android viewPager 自动播放
- Android在代码中设置控件的drawableLeft,drawableRight,drawableTop,drawableBottom。
- Gson的简单使用
- android应用添加欢迎界面
- Android Studio 导入github源码