您的位置:首页 > 其它

View的事件体系---V3.2 View的滑动

2016-04-14 23:32 309 查看
一、View的滑动一般通过以下三种方式实现:


a. 通过View本身提供的ScrollTo/ScrollBy方法

b. 通过动画给View施加平移效果来实现滑动

c. 通过改变View的LayoutParams参数使View重新布局来实现滑动效果

二、使用ScrollTo/ScrollBy

a. 这是View本身提供的实现滑动的方法

b. 通过对比源码发现,scrollBy也是调用了ScrollTo方法,实现了基于当前位置的相对滑动,scrollTo方法实现了基于所传递参数的绝对滑动

c. 在滑动过程中,mScrollX的值总是等于View左边缘和View内容左边缘在水平方向上的距离,mScrollY的值总是等于View上边缘和View内容上边缘在竖直方向上的距离。View的边缘指View的位置,有四个顶点组成,View内容的边缘是指View中的内容的边缘,scrollTo/scrollBy只能改变View内容的位置而不能改变View在布局中的位置

d. mScrollX mScrollY单位为像素,当View左边缘在View内容左边缘的右边时,mScrollX为正值,反之为负值。当View上边缘在View内容上边缘的下边时,mScrollY为正值,反之为负值。

e. 从左往右滑动,那么mScrollX为负值,反之为正值。当从上往下滑动时,mScrollY为负值,反之为正值。

三、使用动画

a. 使用动画是View进行滑动,主要对其translationX translationY两个属性进行修改,可以使用传统的View动画,也可以使用属性动画来完成

b. 采用View动画的话,可以通过anim文件,进行编写,如下

<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="1000" android:fillAfter="true" android:fromXDelta="0" android:fromYDelta="0"
android:toXDelta="100" android:toYDelta="100" android:interpolator="@android:interpolator/accelerate_decelerate" /></set>

c. 属性动画,更为简洁,如下

ObjectAnimator.ofInt(parent,"translationX",0,100).setDuration(1000).start();

d. 传统View动画和属性动画是有区别的,传统的View动画只是从表象上吧View进行了移动,但其本质并没有发生位置改变,如果注册过onclick事件,会发现移动后View点击是无效的,而有效点仍然在原位置,而属性动画的出现,很好的解决了这一问题。

四、通过改变布局参数

a. 通过改变LayoutParams参数,也可以实现View的滑动,示例如下

ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) name.getLayoutParams(); params.leftMargin+=150; params.rightMargin+=150; name.setLayoutParams(params);

五、三种方式对比

a. ScrollTo/ScrollBy:操作简单,适用于对View内容的滑动

b. 动画:操作简单,适用于没有交互的View和实现复杂的动画效果

c. 改变布局参数:操作稍微复杂,适用于有交互的View

完整代码如下:
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.example.zhonglq.myapplication;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

private TextView name;

private RelativeLayout parent;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

name = (TextView) this.findViewById(R.id.name);
parent = (RelativeLayout) this.findViewById(R.id.parent);

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});

// 解决长按屏幕后无法拖动的现象
//        gestureDetector.setIsLongpressEnabled(false);
}

public void move(View view){
Toast.makeText(this,"move",Toast.LENGTH_SHORT).show();
//        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) name.getLayoutParams();
//        params.leftMargin+=150;
//        params.rightMargin+=150;
//        name.setLayoutParams(params);
parent.scrollTo(-30, 30);
ObjectAnimator.ofInt(parent,"translationX",0,100).setDuration(1000).start();
}

GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.OnGestureListener() {
/**
* 手指轻轻触摸屏幕的一瞬间,1个Action_down触发
* @param e
* @return
*/
@Override
public boolean onDown(MotionEvent e) {
return false;
}

/**
* 手指轻轻触摸屏幕,尚未松开或拖动,由1个Action_down触发
* 与onDown相比,强调的是没有松开或者拖动的状态
* @param e
*/
@Override
public void onShowPress(MotionEvent e) {

}

/**
* 手指松开,伴随1个action_up
* @param e
* @return
*/
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}

/**
* 手指按下屏幕并拖动,1个ACTION_DOWN N个ACTION_MOVE
* @param e1
* @param e2
* @param distanceX
* @param distanceY
* @return
*/
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}

/**
* 长按屏幕
* @param e
*/
@Override
public void onLongPress(MotionEvent e) {

}

/**
* 手指按下触摸屏,快速滑动后松开,强调的是快速滑动行为
* @param e1
* @param e2
* @param velocityX
* @param velocityY
* @return
*/
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
});

GestureDetector.OnDoubleTapListener onDoubleTapListener = new GestureDetector.OnDoubleTapListener() {

/**
* 严格的单击行为
* 和onSingleTapUp的区别为,如果触发了onSingleTapConfirmed,那么后面不可能在紧跟着另外一个单击行为,
* 这只可能是单击,而不是双击中的一次单击
* @param e
* @return
*/
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
return false;
}

/**
* 双击 两次连续的单击构成,不可能和onSingleTapConfirmed并存
* @param e
* @return
*/
@Override
public boolean onDoubleTap(MotionEvent e) {
return false;
}

/**
* 表示发生了双击行为,在双击的期间,ACTION_DOWN ACTION_MOVE ACTION_UP都会触发此回调
* @param e
* @return
*/
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
};

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}
}</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: