自定义控件之滑动
来源:互联网 发布:ios11更新不了软件 编辑:程序博客网 时间:2024/06/05 19:25
View滑动的方法是现实绚丽的自定义控件的基础
一般来说实现滑动的方法有三种:
- 通过View本身提供的scrollTo/scrollBy方法来实现
- 通过动画方法
- 通过更改View的LayoutParams,实现重新布局来实现。
一、通过View本身提供的scrollTo/scrollBy方法来实现
scrollTo/scrollBy改变的是控件的内容的而不是控件在布局中的位置。例如设置一个长宽高都是100dp的TextView,效果如下:
scrollTo使用方法是:
/** * x:是在x轴上的偏移量 * y:是在y轴上的偏移量 * 例如从(0,0)偏移到(20,20),那么x=0-20=-20, y=0-20=-20 * 所以,如果从上向下,从左向右,那么偏移量x,y为负值,反之为正值。 */tv.scrollTo(int x,int y);
scrollBy可以多次偏移,再次偏移的时候就以上次偏移的位置作为起始点。具体效果如上图。
tv.scrollBy(int x,int y);
二、通过动画方式
动画的部分下次会详细描述,这次略过。
三、通过更改View的LayoutParams,实现重新布局来实现。
制作一个翻页的界面,在翻页的时候小圆点跟着变化,效果如下:
查看主要代码:
xml布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_test3" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="cn.centran.zx_view_custom.Test3Activity"> <android.support.v4.view.ViewPager android:id="@+id/vp_guide" android:layout_width="match_parent" android:layout_height="match_parent" /> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="30dp" > <LinearLayout android:id="@+id/ll_point_group" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > </LinearLayout> <View android:id="@+id/view_red_point" android:layout_width="10dp" android:layout_height="10dp" android:background="@drawable/shape_point_selected" /> </RelativeLayout></RelativeLayout>
重要代码片段:
/** * 加载小圆点 */for(int i=0;i<imageId.length;i++){ View point = new View(this); //设置圆点背景 point.setBackgroundResource(R.drawable.shape_point_normal); //设置圆点宽高 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(30,30); point.setLayoutParams(params); if(i!=0){ params.leftMargin = 30; } llPointGroup.addView(point);}/** * 获取两个圆点之间的距离 */ //获取视图树 final ViewTreeObserver viewTreeObserver = llPointGroup.getViewTreeObserver(); //添加对试图树中layout过程的监控 viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void onGlobalLayout() { System.out.println("layout"); llPointGroup.getViewTreeObserver().removeOnGlobalLayoutListener(this); pointWidth = llPointGroup.getChildAt(1).getLeft() - llPointGroup.getChildAt(0).getLeft(); } });/** * 监控ViewPager的滑动 */ mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { System.out.println("position::"+position+" positionOffset::"+positionOffset+" positionOffsetPixels::"+positionOffsetPixels); int offset = (int) (pointWidth * positionOffset+pointWidth*position); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mRedPoint.getLayoutParams()); params.leftMargin = offset; mRedPoint.setLayoutParams(params); } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { } });
VelocityTracker介绍:
VelocityTracker是速度跟踪器,用于跟踪手指在滑动过程中的速度,包括竖直速度和水平速度。
//获取速度跟踪器的对象velocityTracker = VelocityTracker.obtain();@Overridepublic boolean onTouchEvent(MotionEvent event) { //添加速度跟踪器监控的事件 velocityTracker.addMovement(event); switch (event.getAction()){ case MotionEvent.ACTION_MOVE: /** * 设置速度跟踪器的时间段 * 1000:表示跟踪1s中滑过的像素 */ velocityTracker.computeCurrentVelocity(1000); xVelocity = velocityTracker.getXVelocity(); yVelocity = velocityTracker.getYVelocity(); break; case MotionEvent.ACTION_UP: Toast.makeText(Test4Activity.this, "水平速度::"+xVelocity+" 竖直速度::"+yVelocity, Toast.LENGTH_SHORT).show(); break; default:break; } return super.onTouchEvent(event);}/** * 当不使用的时候,重置以及释放内存 */ velocityTracker.clear(); velocityTracker.recycle();
因为: 速度 = (终点位置 - 起点位置) / 时间段 , 所以速度有正负值,向下/向右滑动,水平/竖直的速度为正值,反之为负值。
GestureDector详解:
手势检测器,虽然android中有onTouch()方法,但是这个方法太简单了,如果需要处理一些复杂的手势,那么就需要用到gestureDector。
GestureDector这个类提供了两个接口和一个类。
- OnGestureListener接口
- OnDoubleTapListener接口
SimpleOnGestureListener,此类继承了上面两个接口的所有方法,需要哪个方法就实现哪个方法。
GestureDetector mGestureDetector = new GestureDetector(mGestureListener); private GestureDetector.OnGestureListener mGestureListener = new GestureDetector.OnGestureListener(){ ......}@Overridepublic boolean onTouch(View v, MotionEvent event) { return mGestureDetector.onTouchEvent(event);}
弹性滑动:
上面介绍的滑动方法都是生硬的滑动,这次介绍弹性滑动,弹性滑动差不多有三种方法:
- 使用Scroller
- 通过动画
- 通过延时策略
一、使用Scroller
scroller需要与computeScroll配合使用:
Scroller mScroller = new Scroller(context);public void smoothScrollTo(int destX,int destY,int durationTime){ int scrollX = getScrollX(); int scrollY = getScrollY(); mScroller.startScroll(scrollX,scrollX,destX,destY,durationTime); invalidate();}@Overridepublic void computeScroll() { super.computeScroll(); if(mScroller.computeScrollOffset()){ scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); postInvalidate(); }}
当调用smoothScrollTo方法的时候,invalidate()方法会导致View重绘。当View重绘后会在draw方法中调用computeScroll,而computeScroll又会去从Scroller中获取当前的scrollX和scrollY;然后又通过scrollTo实现滑动。接着又调用postInvalidate方法来进行绘制,这次绘制又会导致computeScroll方法的调用(注意此时获取的当前的scrollX和scrollY是上次滑动后的位置),如此反复,直至整个滑动过程结束。
二、通过动画方式
动画的部分下次会详细描述,这次略过。
三、通过延时策略方式
private static final int MESSAGE_TAG = 1;private int mCount = 0;private int TOTAL_COUNT = 30;private int DELAY_TIME = 33;public Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if(msg.what == MESSAGE_TAG){ mCount++; if(mCount<TOTAL_COUNT){ int scrollX = -300/TOTAL_COUNT; btn_moving.scrollBy(scrollX,0); mHandler.sendEmptyMessageDelayed(MESSAGE_TAG,DELAY_TIME); } } }};
- 自定义控件之滑动
- 自定义控件之滑动
- 自定义控件之滑动开关
- 自定义控件之滑动按钮
- 自定义控件专题之二:滑动开关
- iOS自定义控件之滑动横幅
- android 自定义控件之滑动按钮
- Android自定义控件之滑动解锁
- Android自定义控件之滑动开关
- Android进阶自定义控件之滑动开关
- 自定义组合控件之滑动item+删除
- 自定义控件之滑动解锁、圆中嵌字
- Android自定义控件之滑动解锁
- 左右滑动自定义控件
- 自定义控件--滑动删除
- 自定义控件--滑动按钮
- 自定义控件:滑动开关
- 滑动控件自定义使用
- 数字图像处理_matlab
- 5个范例告诉你什么是自适应网页设计
- VC 下Microsoft Speech SDK开发语音识别
- 提高SQL查询效率
- final,finally,finalsize 的区别
- 自定义控件之滑动
- HDU5446 Unknown Treasure[中国剩余定理+Lucas]
- 搭建kafka运行环境
- 质因数分解
- 抽象类与接口
- Tensorflow入门学习笔记
- web.xml配置五个有用的过滤器
- CM和CDH
- html中body属性值类型