2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 安卓View — View (一)

安卓View — View (一)

时间:2018-10-13 21:36:09

相关推荐

安卓View — View (一)

目录

安卓View — View (一)一、 View的基础知识1.什么是View2.View的位置参数3.MotionEvent4.TouchSlop5.VelocityTracker6.GestureDetector 二、View的滑动1.scrollTo/scrollBy2.使用动画View动画属性动画 3.改变布局参数4.滑动方式对比5.跟随手指滑动的View编写 三.弹性滑动1. Scroller2.使用动画3.使用延时策略

安卓View — View (一)

一、 View的基础知识

1.什么是View

在Android中, 控件大致被分为两类,即ViewGroup和View, ViewGroup作为父控件可以包含多个View, 并管理其包含的View控件, View是Android中所有控件的基类,是界面层的空间的一种抽象它代表了一个控件。

2.View的位置参数

View的位置参数主要有

坐标系以父布局左上角为基准的

3.MotionEvent

MotionEvent是指触摸事件的相关细节,在手指触摸时发生的一系列事件中经典的事件有以下几种:

ACTION_DOWN 手指刚接触屏幕ACTION_MOVE 手指在屏幕上移动ACTION_UP 手指从屏幕松开的一瞬间ACTION_CANCEL 时间结束(非人为原因)

通过MotionEvent可以获取到触摸事件的x和y坐标

getX/getY 相对于View左上角的x与y坐标getRawX/getRawY 相对于屏幕左上角的x与y坐标

正常情况下,一次手指触摸的行为会触发一系列点击事件,如:

点击屏幕后立刻松开,ACTION_DOWN -> ACTION_UP点击屏幕后滑动手指后再松开,ACTION_DOWN -> ACTION_MOVE -> … -> ACTION_UP

事件序列:

4.TouchSlop

TouchSlop是系统所能识别的被认为是滑动的最小距离。这是一个常量和设备有关,不同的设备获取的值可能不同。如果滑动起始位置与结束位置的距离小于这个常量可以认为未达到滑动距离的临界值因此认定这个不是滑动提高用户体验。

可以通过以下代码获取:

ViewConfiguration.get(getContext()).getScaledTouchSlop();

5.VelocityTracker

VelocityTracker为速度追踪器,用于追踪手指在滑动过程中的速度,包括水平与竖直方向的速度。

使用方法:

//在onTouchEvent方法中追踪当前点击事件的速度VelocityTracker velocityTracker = VelocityTracker.obtain();velocityTracker.addMovement(event);//获取在1000ms内中手指滑过的像素//速度 =(终点位置 - 起点位置)/ 时间段puteCurrentVelocity(1000);float xVelocity = velocityTracker.getXVelocity();float yVelocity = velocityTracker.getYVelocity();//在不需要使用时调用clear与recycle来重置并回收内存velocityTracker.clear();velocityTracker.recycle();

注意:和Android坐标轴相同方向结果为正,相反方向为负

6.GestureDetector

手势检测,用于辅助检测用户的单击、滑动、长按、双击等行为。

GestureDetector内部的Listener接口:

OnGestureListener,这个Listener监听一些手势,如单击、滑动、长按等操作:OnDoubleTapListener,这个Listener监听双击和单击事件。OnContextClickListener,鼠标右键(加入外设)SimpleOnGestureListener,实现了上面三个接口的类,拥有上面三个的所有回调方法。

package com.skit.view;import android.os.Bundle;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;/*** Author: shuike,* Email: shuike007@,* Date: /11/25.* PS:*/public class MainActivity extends AppCompatActivity {GestureDetector.SimpleOnGestureListener simpleOnGestureListener = new GestureDetector.SimpleOnGestureListener(){//手指轻触并松开@Overridepublic boolean onSingleTapUp(MotionEvent e) {return super.onSingleTapUp(e);}//长按@Overridepublic void onLongPress(MotionEvent e) {super.onLongPress(e);}//按下并拖动@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {return super.onScroll(e1, e2, distanceX, distanceY);}//按下触碰长按并松开@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {return super.onFling(e1, e2, velocityX, velocityY);}//手指轻触屏幕的一瞬间,尚未松开@Overridepublic void onShowPress(MotionEvent e) {super.onShowPress(e);}//手指轻触屏幕的一瞬间@Overridepublic boolean onDown(MotionEvent e) {return super.onDown(e);}//双击@Overridepublic boolean onDoubleTap(MotionEvent e) {return super.onDoubleTap(e);}//发生双击并松开@Overridepublic boolean onDoubleTapEvent(MotionEvent e) {return super.onDoubleTapEvent(e);}//严格的单击@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {return super.onSingleTapConfirmed(e);}//鼠标右键点击时的回调@Overridepublic boolean onContextClick(MotionEvent e) {return super.onContextClick(e);}};@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final GestureDetector gestureDetector = new GestureDetector(this, simpleOnGestureListener);View view = findViewById(R.id.view);view.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {return gestureDetector.onTouchEvent(event);}});}}

比较常用的:

onSingleTapUp(单击)onFling(快速滑动)onScroll(拖动)onLongPress(长按)onDoubleTap(双击)

二、View的滑动

1.scrollTo/scrollBy

为了实现View的滑动,View提供了专门的方法来实现这个功能

scrollTo/scrollBy的区别:

scrollTo是基于参数的绝对滑动。scrollBy是基于参数的相对滑动。注意,两者都是移动View的内容,而不是VIew本身

scrollTo与scrollBy源码

/*** Set the scrolled position of your view. This will cause a call to* {@link #onScrollChanged(int, int, int, int)} and the view will be* invalidated.* @param x the x position to scroll to* @param y the y position to scroll to*/public void scrollTo(int x, int y) {if (mScrollX != x || mScrollY != y) {int oldX = mScrollX;int oldY = mScrollY;mScrollX = x;mScrollY = y;invalidateParentCaches();onScrollChanged(mScrollX, mScrollY, oldX, oldY);if (!awakenScrollBars()) {postInvalidateOnAnimation();}}}/*** Move the scrolled position of your view. This will cause a call to* {@link #onScrollChanged(int, int, int, int)} and the view will be* invalidated.* @param x the amount of pixels to scroll by horizontally* @param y the amount of pixels to scroll by vertically*/public void scrollBy(int x, int y) {//可以看出scrollBy也是调用scrollBy实现的scrollTo(mScrollX + x, mScrollY + y);}

在滑动过程中:

mScrollX的值总是等于View的左边缘和View的内容左边缘在水平方向的距离。

mScrollY的值总是等于View的上边缘和View的内容上边缘在竖直方向的距离

mScrollX与mScrollY只能改变View的内容的位置而不能改变View在布局中的位置。mScrollX和mScrollY的值单位是像素,从左向右滑动mScrollX值为负,否则为正,从上往下滑动mScrollY值为负,否则为正。

2.使用动画

通过动画我们能让一个View进行平移,而平移就是一种滑动。使用动画来移动View主要是操作View的translationX与translationY,可以使用View补间动画或属性动画。

View动画

<?xml version="1.0" encoding="utf-8"?><set xmlns:android="/apk/res/android"android:fillAfter="true"><translateandroid:duration="100"android:fromXDelta="0"android:fromYDelta="0"android:interpolator="@android:anim/linear_interpolator"android:toXDelta="100"android:toYDelta="100" /></set>

Animation animation = AnimationUtils.loadAnimation(this,R.anim.view_translate);view.startAnimation(animation);

通过GIF可以看出来 View动画是对View的影像进行操作的,也就是说View动画并不能真正的改变View的位置。

属性动画

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view,"translationX",0,100).setDuration(1000);objectAnimator.start();

通过GIF可以看出来属性动画是真正改变View的位置。

但它是从Android3.0开始推出的。

3.改变布局参数

改变布局参数,即会改变LayouParams的参数,如:要将一个View右移100像素点,我们可以把该View的LayoutParams的marginLeft参数增加100就可以实现

ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();params.leftMargin += 100;view.requestLayout();//或者//view.setLayoutParams(params);

4.滑动方式对比

上面分别使用三种方式实现了View的滑动,那么各个方式的区别是什么样的呢?

5.跟随手指滑动的View编写

@Overridepublic boolean onTouchEvent(MotionEvent event) {float x = event.getRawX();float y = event.getRawY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:break;case MotionEvent.ACTION_MOVE:float deltaX = x - mLastX;float deltaY = y - mLastY;float translationX = (getTranslationX() + deltaX);float translationY = (getTranslationY() + deltaY);setTranslationX(translationX);setTranslationY(translationY);break;}mLastX = x;mLastY = y;return true;}

三.弹性滑动

1. Scroller

Scroller弹性滑动对象,用于实现View的弹性滑动,在使用View的scrollTo/scroolBy方法来滑动时过程是一瞬间完成的,没有过渡效果对用户体验不好,这时可以使用Scroller来实现过度滑动,Scroller本身无法让View弹性滑动,需要配合、View的computeScroll方法配合使用。

使用方法:

//第一步private Scroller mScroller;mScroller = new Scroller(context);//第二步,调用startScroll()方法来初始化滚动数据并刷新界面mScroller.startScroll(getScrollX(), 0, dx, 0);//第三步,重写computeScroll方法,并在其内部完成平滑滚定的逻辑@Overridepublic void computeScroll() {if(puteScrollOffset()){scrollTo(mScroller.getCurrX(), mScroller.getCurrY());postInvalidate();}}

Scroll相关源码:

//startX与startY为滑动的起点,dx与dy为要滑动的距离,duration为滑动的时间默认为250public void startScroll(int startX, int startY, int dx, int dy, int duration) {mMode = SCROLL_MODE;//模式在之后的computeScrollOffset做判断使用mFinished = false;mDuration = duration;mStartTime = AnimationUtils.currentAnimationTimeMillis();mStartX = startX;mStartY = startY;mFinalX = startX + dx;mFinalY = startY + dy;mDeltaX = dx;mDeltaY = dy;mDurationReciprocal = 1.0f / (float) mDuration;}public boolean computeScrollOffset() {if (mFinished) {return false;}int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);if (timePassed < mDuration) {switch (mMode) {case SCROLL_MODE:final float x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal);mCurrX = mStartX + Math.round(x * mDeltaX);mCurrY = mStartY + Math.round(x * mDeltaY);break;.....}}else {mCurrX = mFinalX;mCurrY = mFinalY;mFinished = true;}return true;}

2.使用动画

动画本身就是一种渐进的过程,因此通过它来实现的滑动天然就具有弹性效果,比如将一个View在100ms内向右移动100像素。

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view,"translationX",0,100).setDuration(1000);objectAnimator.start();

3.使用延时策略

private static final int MESSAGE_SCROLL_TO = 1;private static final int FRAME_COUNT = -300;private static final int DELAYED_TIME = 10;Handler mHandler = new Handler(){@Overridepublic void handleMessage(@NonNull Message msg) {switch (msg.what) {case MESSAGE_SCROLL_TO:Toast.makeText(MainActivity.this, "shoudaole", Toast.LENGTH_SHORT).show();mCount++;if (mCount >= FRAME_COUNT) {float fraction = mCount / FRAME_COUNT;int scrollX = (int) (fraction * 100);view.scrollTo(scrollX, 0 );mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO, DELAYED_TIME);}break;}}};

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。