Android实现滑动的几种方法
来源:互联网 发布:哪个淘宝课程好 编辑:程序博客网 时间:2024/09/21 09:29
下面通过一个例子来总结实现滑动的几种方式,例子的主要功能就是让我们的自定义View能够随着手指的移动而移动。
布局文件如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <com.scu.lly.dragviewtest.view.DragView android:layout_width="100dp" android:layout_height="100dp" /></LinearLayout>
方式一:layout方法
在View进行绘制时,会调用onLayout()方法来设置显示的位置,因此,我们可以通过修改View的left、top、right、bottom四个属性来控制View的坐标。要控制View随手指滑动,因此需要在onTouchEvent()事件中进行滑动控制。代码如下:
public class DragView extends View{ private int mLastX; private int mLastY; public DragView(Context context) { super(context); init(); } public DragView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public DragView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init(){ setBackgroundColor(Color.BLUE); } @Override public boolean onTouchEvent(MotionEvent ev) { int x = (int) ev.getX(); int y = (int) ev.getY(); switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: mLastX = x; mLastY = y; break; case MotionEvent.ACTION_MOVE: int offsetX = x - mLastX; int offsetY = y - mLastY; //调整layout的四个坐标 layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY); break; } return true; }}
方式二:offsetLeftAndRight()和offsetTopAndBottom()
这两个方法其实是对上面那种layout设置方式的封装、简化,在layout中,左left、右right两个方向都是加上offsetX,上top、下bottom两个方向都是加上offsetY,为了简化设置四个方向,Android提供了offsetLeftAndRight()来代替左右方向的设置,用offsetTopAndBottom()来代替上下方向的设置。
我们只需要修改上面代码ACTION_MOVE的部分,如下:
<span style="white-space:pre"></span>case MotionEvent.ACTION_MOVE: int offsetX = x - mLastX; int offsetY = y - mLastY; //调整layout的四个坐标 //layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY); //使用简写形式 offsetLeftAndRight(offsetX); offsetTopAndBottom(offsetY); break;
方式三:LayoutParams
LayoutParams保存了一个View的布局参数,因此我们可以通过动态改变LayoutParams中的布局参数来达到改变View的位置效果。通过getLayoutParams()方法来获取View的LayoutParams,这里获取到的LayoutParams需要根据View所在父布局的类型来设置不同的类型,比如,我们这个自定义View是放在LinearLayout中的,那么通过getLayoutParams()获取到的就是LinearLayout.LayoutParams。因此,通过getLayoutParams()获取到LayoutParams的前提就是这个View需要有一个父布局。
同样,我们只需要修改上面代码ACTION_MOVE的部分,如下:
case MotionEvent.ACTION_MOVE: int offsetX = x - mLastX; int offsetY = y - mLastY; LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams(); lp.leftMargin = getLeft() + offsetX; lp.topMargin = getTop() + offsetY; setLayoutParams(lp); break;
可以看到,通过LayoutParams改变一个View的位置时,改变的是这个View的Margin属性,这也是为什么这种方式一定要有父布局的原因,只有有了父布局,margin属性的设置才会起作用。
对于使用LayoutParams这种方式改变View位置,如果我们不想考虑父布局的类型,还可以使用ViewGroup.MarginLayoutParams来进行设置,这样也更加方便。如下:
case MotionEvent.ACTION_MOVE: int offsetX = x - mLastX; int offsetY = y - mLastY; //LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams(); ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams(); lp.leftMargin = getLeft() + offsetX; lp.topMargin = getTop() + offsetY; setLayoutParams(lp); break;
效果是一样的。
方式四:scrollTo与scrollBy
关于scrollTo()和scrollBy()方法,我这篇文章《Android Scroller大揭秘》中有详细介绍。
使用scrollTo()和scrollBy()方法需要注意的一点是,scrollTo()和scrollBy()方法移动的是View的content,即让View的内容移动,如果在ViewGroup中使用scrollTo()和scrollBy()方法,那么移动的将是所有的子View,如果在View中使用,那么移动的将是View的内容。例如,TextView,content就是它的文本,ImageView,content就是它的drawable对象。
因此,上面例子中我们如果直接这样使用:
scrollBy(offsetX,offsetY);
发现View并没有移动,但其实是发生了移动的,只不过此时移动的是View中的内容,而我们例子中的content什么也没有。
所以,我们要想使这个View发生移动,我们就应该在View所在的ViewGroup中使用scrollBy或scrollTo方法来进行移动。同时,使用者两个方法进行移动的时候,注意此时的坐标方向与平常是相反的,具体在《Android Scroller大揭秘》有讲解。代码如下:
case MotionEvent.ACTION_MOVE: //int offsetX = x - mLastX; //int offsetY = y - mLastY; //此时,计算坐标是相反的 int offsetX = mLastX - x; int offsetY = mLastY - y; //让View所在的ViewGroup进行移动 ((View)getParent()).scrollBy(offsetX,offsetY); break;
方式五:Scroller
通过Scroller这个辅助类,配合scrollTo和scrollBy可以实现一些更加高级的滑动效果,关于Scroller类的具体介绍,同样在这篇文章中有详解《Android Scroller大揭秘》。
这里,我们只是结合上面这个例子实现一个简单的功能,当我们滑动完毕抬起手指后,View自动回弹到原来的位置。代码如下:
public class DragView extends View{private int mLastX; private int mLastY; private Scroller mScroller; public DragView(Context context) { super(context); init(context); } public DragView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public DragView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context){ setBackgroundColor(Color.BLUE); mScroller = new Scroller(context); } @Override public boolean onTouchEvent(MotionEvent ev) { int x = (int) ev.getX(); int y = (int) ev.getY(); switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: mLastX = x; mLastY = y; break; case MotionEvent.ACTION_MOVE: //int offsetX = x - mLastX; //int offsetY = y - mLastY; //此时,计算坐标是相反的 int offsetX = mLastX - x; int offsetY = mLastY - y; //让View所在的ViewGroup进行移动 ((View)getParent()).scrollBy(offsetX,offsetY); break; case MotionEvent.ACTION_UP: View viewGroup = (View) getParent(); mScroller.startScroll(viewGroup.getScrollX(),viewGroup.getScrollY(),-viewGroup.getScrollX(),-viewGroup.getScrollY()); //记住需要invalidate invalidate(); break; } return true;} @Override public void computeScroll() { super.computeScroll(); if(mScroller.computeScrollOffset()){ ((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); //记住,需要不断调用invalidate进行重绘 invalidate(); } }}
以上五种方法就是常用的滑动View的方法。还有两种方式能够控制一个View的移动效果:属性动画和使用ViewDragHelper,对于这两种方法,大家可以查阅网上资料,就不详细介绍了。
(以上内容来源于看《Android群英传》的总结)
10 2
- Android实现滑动的几种方法
- Android 实现滑动的几种方法(二)LayoutParams
- Android实现控件滑动的几种方法
- 关于Android实现滑动返回的几种方法总结
- 实现滑动的几种方法
- 实现滑动的几种简单方法
- 实现View 滑动的几种方法
- 实现view滑动的几种方法
- 【Android View事件(四)】View滑动与实现滑动的几种方法
- android view滑动的几种方法
- Android实现滑动的几种方式
- Android 实现滑动的几种方法(一)onLayout方法 和 offsetLeftAndRight()与offsetTopAndBottom();
- Android中实现滑动(拖动)的几种方法,玩转SlideMenu
- Android 实现滑动的几种方法(三)scrollTo 与 scrollBy
- Android中实现滑动(拖动)的几种方法,玩转SlideMenu
- 读书笔记之安卓实现滑动的几种方法
- View弹性滑动的几种实现方法
- vue过渡效果的几种实现方法、各种滑动
- 杭电OJ A+B for Input-Output Practice (I)
- expire_logs_day binlog自动过期清理binlog
- WebAPI的一种单元测试方案
- 欢迎使用CSDN-markdown编辑器
- 多线程 - 阻塞栈blockingDeque
- Android实现滑动的几种方法
- UML中关联(Association)、聚合(Aggregation)和合成(Composition)之间的区别
- 角色类设计2
- Python 获取对象信息
- 几种高速缓存算法
- map hash_map unordered_map 性能测试
- iOS开发经验:高德地图折线或者图形等覆盖物的适配显示
- 2年经验须知
- union和union all及区别