H5W3
当前位置:H5W3 > java > 正文

【Java】Android中View的滑动

Android中View的滑动

小二玩编程发布于 16 分钟前

在生活中我们使用 Android 的 App 经常会看到一些炫丽的动态界面,出现这种效果很多是因为 View 的滑动,比如 RecyclerView 的滑动,掌握 View 的滑动方式,我们也能做出这样的效果;实现 View 的滑动常见的有5种方法,它们分别是 使用 scrollTo/scrollBy、使用动画、改变布局参数和使用 layout,下面将对它们一一进行介绍。

1、使用 scrollTo/scrollBy
View提供了 scrollTo(int x,int y) 和 scrollBy(int x,int y) 这两个方法实现了它的滑动,具体实现代码(基于 Android Api 27)如下所示:

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();
}
}
}
public void scrollBy(int x, int y) {
scrollTo(mScrollX + x, mScrollY + y);
}

从scrollTo(int x,int y) 和 scrollBy(int x,int y) 这两个方法总结得出,scrollTo(int x,int y) 实现了所传递参数的绝对滑动,而 scrollBy(int x,int y) 实现了当前位置的相对滑动,因为它调用了 scrollTo(int x,int y) 方法。在这2个方法中,出现了 mScrollX 和 mScrollY 这两个成员变量,其中 mScrollX 表示 View 的左边缘和 View 内容左边缘在水平方向的距离,mScrollY 表示 View 上边缘和 View 内容上边缘在垂直方向上的距离。下面写一个例子来使用 scrollBy(int x,int y) 方法;首先新建一个布局文件 activity_view_general_slide.xml,它的代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout        xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.administrator.androidart.activites.ViewGeneralSlideActivity">
<TextView
android:id="@+id/tv_scroll"
android:layout_width="match_parent"
android:layout_marginTop="20px"
android:text="scrollBy滑动"
android:background="#00FF00"
android:onClick="onClickView"
android:gravity="bottom"
android:layout_height="match_parent" />
</LinearLayout>

然后再新建一个Java文件,名字为 ViewGeneralSlideActivity,代码如下所示:

private TextView mTv;
private MyHandler mHandler = null;
private int mSlideY = 20;
private int mSlideX = 20;
private MyThread thread = null;
private boolean isRunThread = true;
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mTv.scrollBy(0,mSlideY);
mSlideY += 10;
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_general_slide);
mTv = findViewById(R.id.tv_scroll);
mHandler = new MyHandler();
thread = new MyThread();
}
public void onClickView(View view) {
thread.start();
}
class MyThread extends Thread {
@Override
public void run() {
super.run();
while (isRunThread) {
try {
Thread.sleep(500);
sendMessage();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
isRunThread = false;
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
}
}
private void sendMessage() {
Message message = Message.obtain();
mHandler.sendMessage(message);
}

没点击“scrollBy滑动”控件之前的效果如下所示:
【Java】Android中View的滑动

点击“scrollBy滑动”控件之后的效果如下所示:
【Java】Android中View的滑动

注意:不管是 scrollBy(int x,int y) 还是 scrollTo(int x,int y) 方法,滑动的并非是 View 本身,而是 View 的内容。

2、使用动画

使用动画来移动 View ,是通过 View 的 translationX 和 translationY 这两个属性来实现的,它即可以采用传统的 View 动画,也可以采用属性动画;在使用属性动画方面,如果要在 Android 3.0以下版本使用,那么就要使用到开源动画库 nineoldandroids,它的官方地址为:http://nineoldandroids.com/ 。下面举个例子用代码实现使用 View 动画来移动。

2、1 采用传统的 View 动画

(1) 在 res 目录新建 anim 文件夹并在 anim 文件夹下创建 view_translate.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:zAdjustment="normal">
<translate android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="200"
android:toYDelta="200"
android:duration="3000"
/>
</set>

(2) 新建一个 Java 文件,名字叫 AnimationActivity,并实现它的代码,如下所示:

private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animation);
mTv = findViewById(R.id.tv);
}
public void onClick(View view) {
Animation animation = AnimationUtils.loadAnimation(this, R.anim.view_translate);
mTv.startAnimation(animation);
}

(3) 在 layout 文件夹下新建一个 activity_animation.xml 文件,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="demo1.xe.com.myapplication2.AnimationActivity">
<Button android:layout_width="match_parent"
android:text="点击该按钮可移动view"
android:onClick="onClick"
android:layout_height="wrap_content" />
<TextView android:id="@+id/tv"
android:layout_width="300px"
android:gravity="center"
android:text="可移动的传统view"
android:background="#FF0000"
android:layout_height="wrap_content" />
</LinearLayout>

没点击 “点击该按钮可移动view” 这个按钮之前,它运行的效果图如下所示:

【Java】Android中View的滑动

点击 “点击该按钮可移动view” 这个按钮之后,它运行时移动的过程中,某一瞬间的效果图如下所示:

【Java】Android中View的滑动

2、2 使用属性动画移动

(1) 为了兼容 Android 3.0 以下版本的手机,在项目 app 目录下的 build.gradle文件中添加 nineoldandroids 的依赖:

implementation 'com.nineoldandroids:library:2.4.0'

(2) 新建一个 Java 文件,名字叫 Animation2Activity,它的代码如下所示:

private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animation2);
mTv = findViewById(R.id.tv);
}
public void onClick(View view) {
ObjectAnimator.ofFloat(mTv,"translationY",0,300).setDuration(1000).start();
}
public void onClick2(View view) {
Toast.makeText(this, "点击了“可移动的属性view”",   Toast.LENGTH_SHORT).show();
}

(3) 在 layout 文件夹下新建一个 activity_animation2.xml 文件,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="demo1.xe.com.myapplication2.AnimationActivity">
<Button android:layout_width="match_parent"
android:text="点击该按钮可属性动画移动view"
android:onClick="onClick"
android:layout_height="wrap_content" />
<TextView android:id="@+id/tv"
android:layout_width="300px"
android:gravity="center"
android:text="可移动的属性view"
android:background="#FF0000"
android:onClick="onClick2"
android:layout_height="wrap_content" />
</LinearLayout>

没点击 “点击该按钮可属性动画移动view” 之前,它的运行效果图如下所示:

【Java】Android中View的滑动

点击 “点击该按钮可属性动画移动view” 这个按钮之后,它运行时移动的过程中,某一瞬间的效果图如下所示:

【Java】Android中View的滑动

对以上使用动画的例子进行总结得出:(1) 传统的 View 动画只是对影像做移动,并不是真正的改变 View 的位置,它的 fillAfter 属性默认值为 false,也就等同于做完动画之后会回到原位置;当 fillAfter 属性设置为 true 的时候,View 做完动画后,影像不会回到原始的位置,但如果在该 View 做一个事件监听,点击做完动画后的 View 是不会响应事件的,点击 View 的原始位置就会响应事件,因为在系统眼里 View 做完动画之后它的位置没有发生改变。(2) 属性动画在 Android 3.0版本以下的手机不可以用,要想使用,必须添加 nineoldandroids 这个依赖酷;属性动画不是对影像做移动,而是真正的改变了 View 的位置,如果在该 View 做一个事件监听,点击 View 的原始位置是不会有事件响应的,而点击做完动画之后的位置就会有事件响应。

3、改变布局参数

通过改变布局参数来实现 View 的滑动的思路有2个:(1) 向右移动一个View,只需要把它的 marginLeft 参数增大,向其它方向移动同理,只需改变相应的 margin 参数;(2) 要移动的 View 的旁边预先放一个 View,它的初始化宽度为0,然后要想右移动View,只需把预先放置的那个View的宽度增大,这样就把要移动的 View “推”到右边了。示例如下所示:

(1) 新建一个布局文件,名字叫 activity_change_layout_parameter.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="demo1.xe.com.myapplication2.ChangeLayoutParameterActivity">
<Button android:layout_width="match_parent"
android:text="点击我可移动第一个View"
android:onClick="onClick"
android:layout_height="wrap_content" />
<Button android:layout_width="match_parent"
android:text="点击我可移动第二个View"
android:onClick="onClick2"
android:layout_height="wrap_content" />
<TextView android:id="@+id/tv"
android:layout_width="350px"
android:onClick="onClick3"
android:text="改变布局参数可移动的View"
android:layout_height="wrap_content" />
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<View android:id="@+id/view"
android:layout_width="0px"
android:layout_height="1px"/>
<TextView android:id="@+id/tv2"
android:layout_width="350px"
android:onClick="onClick4"
android:text="改变布局参数可移动的View"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>

新建一个 Java 文件,名字叫 ChangeLayoutParameterActivity,它的代码如下所示:

TextView mTv;
View mView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_change_layout_parameter);
mTv = findViewById(R.id.tv);
mView = findViewById(R.id.view);
}
public void onClick(View view) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mTv.getLayoutParams();
params.leftMargin += 200;
params.width += 200;
mTv.requestLayout();
}
public void onClick2(View view) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mView.getLayoutParams();
params.width += 200;
mView.requestLayout();
}
public void onClick3(View view) {
Toast.makeText(this,"点击了“改变布局参数可移动的第一个View” ",Toast.LENGTH_SHORT).show();
}
public void onClick4(View view) {
Toast.makeText(this,"点击了“改变布局参数可移动的第二个View” ",Toast.LENGTH_SHORT).show();
}

没点击 “点击我可移动第一个View” 按钮之前,效果图如下所示:

【Java】Android中View的滑动

点击 “点击我可移动第一个View” 按钮之后,效果图如下所示:

【Java】Android中View的滑动

对以上改变布局参数移动 View 进行总结:不管是对 View 的 marginLeft 参数进行增大;还是要移动的 View 的旁边预先放一个 View,然后要向右移动View;他们两种方法都实现了 View 真正位置的移动,而不是 View 影像的移动;如果在 移动的 View 做事件监听,点击原始位置不会事件响应,点击移动后的位置会有事件响应。

4、使用 layout

使用 layout 移动 View 的思路是这样的:在View的onTouchEvent方法中对MotionEvent中的坐标进行记录,记录按下的时候记录,在移动的时候计算他们的偏移量,调用layout()对view的位置进行重绘制;下面举个例子:

(1) 新建一个布局文件,名叫 activity_use_layout.xml :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="demo1.xe.com.myapplication2.UseLayoutActivity">
<TextView android:id="@+id/tv"
android:layout_width="wrap_content"
android:text="使用 Layout移动View"
android:onClick="onClick"
android:layout_height="wrap_content" />
</RelativeLayout>

(2) 新建一个 Java 文件,名叫 UseLayoutActivity,它的实现代码如下所示:

TextView mTv;
private int lastX,lastY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_use_layout);
mTv = findViewById(R.id.tv);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getRawX();
int y = (int) event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
mTv.layout(mTv.getLeft()+offsetX,
mTv.getTop()+offsetY,
mTv.getRight()+offsetX,
mTv.getBottom()+offsetY);
lastX = x;
lastY = y;
break;
}
return true;
}
public void onClick(View v){
Toast.makeText(this," 点击了 “使用 Layout移动View” 按钮 ",Toast.LENGTH_SHORT).show();
}

没滑动屏幕之前的效果图如下所示:

【Java】Android中View的滑动

滑动屏幕某一瞬间的效果图如下所示:

【Java】Android中View的滑动

对以上使用 layout 移动 View 进行总结:使用 layout 移动 View,改变的不是 View 的影像,而是 View 真正的位置,所以如果要设置 View 的事件监听,点击移动后的 View 才会响应事件;使用 layout 移动 View 是和 Activity 的触摸事件结合使用的,触摸的时候获取相对于屏幕触摸的x 和 y 坐标,然后手指移动的过程中计算出移动的距离再加上 View 相对于父视图的位置,得到 View 移动后的位置,最后 View 使用 layout 方法 重新布局再进行重新绘画。

好了,本篇文章写到这里就结束了,由于本人技术水平有限,难免会有出错的地方,欢迎批评指正,谢谢大家的阅读,另外附上Android的View滑动demo

【Java】Android中View的滑动关注微信公众号,阅读更多有趣的技术文章

javaandroid
阅读 16发布于 16 分钟前
本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议
avatar

小二玩编程

活到老,学到老。

1 声望
1 粉丝

0 条评论
得票时间

avatar

小二玩编程

活到老,学到老。

1 声望
1 粉丝

宣传栏

在生活中我们使用 Android 的 App 经常会看到一些炫丽的动态界面,出现这种效果很多是因为 View 的滑动,比如 RecyclerView 的滑动,掌握 View 的滑动方式,我们也能做出这样的效果;实现 View 的滑动常见的有5种方法,它们分别是 使用 scrollTo/scrollBy、使用动画、改变布局参数和使用 layout,下面将对它们一一进行介绍。

1、使用 scrollTo/scrollBy
View提供了 scrollTo(int x,int y) 和 scrollBy(int x,int y) 这两个方法实现了它的滑动,具体实现代码(基于 Android Api 27)如下所示:

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();
}
}
}
public void scrollBy(int x, int y) {
scrollTo(mScrollX + x, mScrollY + y);
}

从scrollTo(int x,int y) 和 scrollBy(int x,int y) 这两个方法总结得出,scrollTo(int x,int y) 实现了所传递参数的绝对滑动,而 scrollBy(int x,int y) 实现了当前位置的相对滑动,因为它调用了 scrollTo(int x,int y) 方法。在这2个方法中,出现了 mScrollX 和 mScrollY 这两个成员变量,其中 mScrollX 表示 View 的左边缘和 View 内容左边缘在水平方向的距离,mScrollY 表示 View 上边缘和 View 内容上边缘在垂直方向上的距离。下面写一个例子来使用 scrollBy(int x,int y) 方法;首先新建一个布局文件 activity_view_general_slide.xml,它的代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout        xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.administrator.androidart.activites.ViewGeneralSlideActivity">
<TextView
android:id="@+id/tv_scroll"
android:layout_width="match_parent"
android:layout_marginTop="20px"
android:text="scrollBy滑动"
android:background="#00FF00"
android:onClick="onClickView"
android:gravity="bottom"
android:layout_height="match_parent" />
</LinearLayout>

然后再新建一个Java文件,名字为 ViewGeneralSlideActivity,代码如下所示:

private TextView mTv;
private MyHandler mHandler = null;
private int mSlideY = 20;
private int mSlideX = 20;
private MyThread thread = null;
private boolean isRunThread = true;
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mTv.scrollBy(0,mSlideY);
mSlideY += 10;
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_general_slide);
mTv = findViewById(R.id.tv_scroll);
mHandler = new MyHandler();
thread = new MyThread();
}
public void onClickView(View view) {
thread.start();
}
class MyThread extends Thread {
@Override
public void run() {
super.run();
while (isRunThread) {
try {
Thread.sleep(500);
sendMessage();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
isRunThread = false;
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
}
}
private void sendMessage() {
Message message = Message.obtain();
mHandler.sendMessage(message);
}

没点击“scrollBy滑动”控件之前的效果如下所示:
【Java】Android中View的滑动

点击“scrollBy滑动”控件之后的效果如下所示:
【Java】Android中View的滑动

注意:不管是 scrollBy(int x,int y) 还是 scrollTo(int x,int y) 方法,滑动的并非是 View 本身,而是 View 的内容。

2、使用动画

使用动画来移动 View ,是通过 View 的 translationX 和 translationY 这两个属性来实现的,它即可以采用传统的 View 动画,也可以采用属性动画;在使用属性动画方面,如果要在 Android 3.0以下版本使用,那么就要使用到开源动画库 nineoldandroids,它的官方地址为:http://nineoldandroids.com/ 。下面举个例子用代码实现使用 View 动画来移动。

2、1 采用传统的 View 动画

(1) 在 res 目录新建 anim 文件夹并在 anim 文件夹下创建 view_translate.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:zAdjustment="normal">
<translate android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="200"
android:toYDelta="200"
android:duration="3000"
/>
</set>

(2) 新建一个 Java 文件,名字叫 AnimationActivity,并实现它的代码,如下所示:

private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animation);
mTv = findViewById(R.id.tv);
}
public void onClick(View view) {
Animation animation = AnimationUtils.loadAnimation(this, R.anim.view_translate);
mTv.startAnimation(animation);
}

(3) 在 layout 文件夹下新建一个 activity_animation.xml 文件,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="demo1.xe.com.myapplication2.AnimationActivity">
<Button android:layout_width="match_parent"
android:text="点击该按钮可移动view"
android:onClick="onClick"
android:layout_height="wrap_content" />
<TextView android:id="@+id/tv"
android:layout_width="300px"
android:gravity="center"
android:text="可移动的传统view"
android:background="#FF0000"
android:layout_height="wrap_content" />
</LinearLayout>

没点击 “点击该按钮可移动view” 这个按钮之前,它运行的效果图如下所示:

【Java】Android中View的滑动

点击 “点击该按钮可移动view” 这个按钮之后,它运行时移动的过程中,某一瞬间的效果图如下所示:

【Java】Android中View的滑动

2、2 使用属性动画移动

(1) 为了兼容 Android 3.0 以下版本的手机,在项目 app 目录下的 build.gradle文件中添加 nineoldandroids 的依赖:

implementation 'com.nineoldandroids:library:2.4.0'

(2) 新建一个 Java 文件,名字叫 Animation2Activity,它的代码如下所示:

private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animation2);
mTv = findViewById(R.id.tv);
}
public void onClick(View view) {
ObjectAnimator.ofFloat(mTv,"translationY",0,300).setDuration(1000).start();
}
public void onClick2(View view) {
Toast.makeText(this, "点击了“可移动的属性view”",   Toast.LENGTH_SHORT).show();
}

(3) 在 layout 文件夹下新建一个 activity_animation2.xml 文件,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="demo1.xe.com.myapplication2.AnimationActivity">
<Button android:layout_width="match_parent"
android:text="点击该按钮可属性动画移动view"
android:onClick="onClick"
android:layout_height="wrap_content" />
<TextView android:id="@+id/tv"
android:layout_width="300px"
android:gravity="center"
android:text="可移动的属性view"
android:background="#FF0000"
android:onClick="onClick2"
android:layout_height="wrap_content" />
</LinearLayout>

没点击 “点击该按钮可属性动画移动view” 之前,它的运行效果图如下所示:

【Java】Android中View的滑动

点击 “点击该按钮可属性动画移动view” 这个按钮之后,它运行时移动的过程中,某一瞬间的效果图如下所示:

【Java】Android中View的滑动

对以上使用动画的例子进行总结得出:(1) 传统的 View 动画只是对影像做移动,并不是真正的改变 View 的位置,它的 fillAfter 属性默认值为 false,也就等同于做完动画之后会回到原位置;当 fillAfter 属性设置为 true 的时候,View 做完动画后,影像不会回到原始的位置,但如果在该 View 做一个事件监听,点击做完动画后的 View 是不会响应事件的,点击 View 的原始位置就会响应事件,因为在系统眼里 View 做完动画之后它的位置没有发生改变。(2) 属性动画在 Android 3.0版本以下的手机不可以用,要想使用,必须添加 nineoldandroids 这个依赖酷;属性动画不是对影像做移动,而是真正的改变了 View 的位置,如果在该 View 做一个事件监听,点击 View 的原始位置是不会有事件响应的,而点击做完动画之后的位置就会有事件响应。

3、改变布局参数

通过改变布局参数来实现 View 的滑动的思路有2个:(1) 向右移动一个View,只需要把它的 marginLeft 参数增大,向其它方向移动同理,只需改变相应的 margin 参数;(2) 要移动的 View 的旁边预先放一个 View,它的初始化宽度为0,然后要想右移动View,只需把预先放置的那个View的宽度增大,这样就把要移动的 View “推”到右边了。示例如下所示:

(1) 新建一个布局文件,名字叫 activity_change_layout_parameter.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="demo1.xe.com.myapplication2.ChangeLayoutParameterActivity">
<Button android:layout_width="match_parent"
android:text="点击我可移动第一个View"
android:onClick="onClick"
android:layout_height="wrap_content" />
<Button android:layout_width="match_parent"
android:text="点击我可移动第二个View"
android:onClick="onClick2"
android:layout_height="wrap_content" />
<TextView android:id="@+id/tv"
android:layout_width="350px"
android:onClick="onClick3"
android:text="改变布局参数可移动的View"
android:layout_height="wrap_content" />
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<View android:id="@+id/view"
android:layout_width="0px"
android:layout_height="1px"/>
<TextView android:id="@+id/tv2"
android:layout_width="350px"
android:onClick="onClick4"
android:text="改变布局参数可移动的View"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>

新建一个 Java 文件,名字叫 ChangeLayoutParameterActivity,它的代码如下所示:

TextView mTv;
View mView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_change_layout_parameter);
mTv = findViewById(R.id.tv);
mView = findViewById(R.id.view);
}
public void onClick(View view) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mTv.getLayoutParams();
params.leftMargin += 200;
params.width += 200;
mTv.requestLayout();
}
public void onClick2(View view) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mView.getLayoutParams();
params.width += 200;
mView.requestLayout();
}
public void onClick3(View view) {
Toast.makeText(this,"点击了“改变布局参数可移动的第一个View” ",Toast.LENGTH_SHORT).show();
}
public void onClick4(View view) {
Toast.makeText(this,"点击了“改变布局参数可移动的第二个View” ",Toast.LENGTH_SHORT).show();
}

没点击 “点击我可移动第一个View” 按钮之前,效果图如下所示:

【Java】Android中View的滑动

点击 “点击我可移动第一个View” 按钮之后,效果图如下所示:

【Java】Android中View的滑动

对以上改变布局参数移动 View 进行总结:不管是对 View 的 marginLeft 参数进行增大;还是要移动的 View 的旁边预先放一个 View,然后要向右移动View;他们两种方法都实现了 View 真正位置的移动,而不是 View 影像的移动;如果在 移动的 View 做事件监听,点击原始位置不会事件响应,点击移动后的位置会有事件响应。

4、使用 layout

使用 layout 移动 View 的思路是这样的:在View的onTouchEvent方法中对MotionEvent中的坐标进行记录,记录按下的时候记录,在移动的时候计算他们的偏移量,调用layout()对view的位置进行重绘制;下面举个例子:

(1) 新建一个布局文件,名叫 activity_use_layout.xml :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="demo1.xe.com.myapplication2.UseLayoutActivity">
<TextView android:id="@+id/tv"
android:layout_width="wrap_content"
android:text="使用 Layout移动View"
android:onClick="onClick"
android:layout_height="wrap_content" />
</RelativeLayout>

(2) 新建一个 Java 文件,名叫 UseLayoutActivity,它的实现代码如下所示:

TextView mTv;
private int lastX,lastY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_use_layout);
mTv = findViewById(R.id.tv);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getRawX();
int y = (int) event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
mTv.layout(mTv.getLeft()+offsetX,
mTv.getTop()+offsetY,
mTv.getRight()+offsetX,
mTv.getBottom()+offsetY);
lastX = x;
lastY = y;
break;
}
return true;
}
public void onClick(View v){
Toast.makeText(this," 点击了 “使用 Layout移动View” 按钮 ",Toast.LENGTH_SHORT).show();
}

没滑动屏幕之前的效果图如下所示:

【Java】Android中View的滑动

滑动屏幕某一瞬间的效果图如下所示:

【Java】Android中View的滑动

对以上使用 layout 移动 View 进行总结:使用 layout 移动 View,改变的不是 View 的影像,而是 View 真正的位置,所以如果要设置 View 的事件监听,点击移动后的 View 才会响应事件;使用 layout 移动 View 是和 Activity 的触摸事件结合使用的,触摸的时候获取相对于屏幕触摸的x 和 y 坐标,然后手指移动的过程中计算出移动的距离再加上 View 相对于父视图的位置,得到 View 移动后的位置,最后 View 使用 layout 方法 重新布局再进行重新绘画。

好了,本篇文章写到这里就结束了,由于本人技术水平有限,难免会有出错的地方,欢迎批评指正,谢谢大家的阅读,另外附上Android的View滑动demo

【Java】Android中View的滑动关注微信公众号,阅读更多有趣的技术文章

本文地址:H5W3 » 【Java】Android中View的滑动

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址