android scrollto scrollby 扯一扯
废话不多说,直接上思路---
1:试想一个界面,父布局是LinearLayout,竖直方向排列,然后里面添加两个View,如果我点击第一个View,直接调用第二个View的scrollTo或者scrollBy方法,第二个View会移动吗?给出代码和布局文件----
布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#00ff00"> <View android:layout_width="200dp" android:layout_height="50dp" android:id="@+id/button1" android:background="#ff0000"/> <View android:layout_width="200dp" android:layout_height="50dp" android:id="@+id/button2" android:background="#0000ff"/> </LinearLayout>
分别设置了三种不同的颜色,方便查看效果,接下来是Activity的代码--
public class ActivityText extends Activity implements View.OnClickListener { private View button1; private View button2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_text); button1 = findViewById(R.id.button1); button2 = findViewById(R.id.button2); button1.setOnClickListener(this); } @Override public void onClick(View view) { if (view.getId() == R.id.button1) { // button2.scrollBy(-30, -30); button2.scrollTo(30, 30); } } }
由于很简单,这里就不上传简单的例子了,我直接说现象:他妈的第二个View根本就没有动~,根本就没有效果--
我就开始想了,猜测--是不是必须移动移动View的父容器,它里面的孩子才会移动?好,我就进行了下面的第二个实验--
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#00ff00" android:id="@+id/ll"> <View android:layout_width="200dp" android:layout_height="50dp" android:id="@+id/button1" android:background="#ff0000"/> <View android:layout_width="200dp" android:layout_height="50dp" android:id="@+id/button2" android:background="#0000ff"/> </LinearLayout>
大家注意看,这次我在两个View的父容器中添加了一个id,叫做ll,然后在Activity中获得LinearLayout的引用--
public class ActivityText extends Activity implements View.OnClickListener { private View button1; private View button2; private LinearLayout ll; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_text); ll = (LinearLayout) findViewById(R.id.ll); button1 = findViewById(R.id.button1); button2 = findViewById(R.id.button2); button1.setOnClickListener(this); } @Override public void onClick(View view) { if (view.getId() == R.id.button1) { ll.scrollBy(-30, -30); } } }
注意看onClick的代码,里面我调用LinearLayout的scrollBy方法,LinearLayout里面的两个View竟然神奇的动起来了,这是为什么呢?不过到现在为止可以确定的是调用ViewGroup的scrollBy或者scrollTo方法,该ViewGroup里面的孩子会动起来。假如直接调用非ViewGroup的View的scrollBy或者scrollTo方法,是一点反应也没有的---那我就纳闷了,是不是ViewGroup里面的源代码在dispatchDraw()方法里面执行了什么特别的操作?
查看ViewGroup的dispatchDraw()方法,发现一些蛛丝马迹----
int saveCount = 0; 2777 final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK; 2778 if (clipToPadding) { 2779 saveCount = canvas.save(); 2780 canvas.clipRect(mScrollX + mPaddingLeft, mScrollY + mPaddingTop, 2781 mScrollX + mRight - mLeft - mPaddingRight, 2782 mScrollY + mBottom - mTop - mPaddingBottom); 2783 2784 }
注意看这几句代码,总感觉是这里的原因--现在明确以下,我们直接调用View(非ViewGroup)的scrollTo或者scrollBy方法是没有效果的,说明单个View的绘制里面并没有对mScrollX和mScrollY这两个变量进行特别的操作--,既然不是View的问题,看上面的源代码,我只能找到是ViewGroup里面的问题了--再说明一点,我们调用scrollTo或者scrollBy方法会对mScrollX和mScrollY这两个变量进行操作--。我从上面的代码得出了一个结论:原来是父容器滚动画布后再绘制自己的孩子,这样就孩子就全部动起来了---,那有人就会问了,要是我不想动全部的孩子,就只是想动第二个View呢?此时你应该想到了办法了,既然是操作孩子的父容器,那么我们只需要在你要移动的View的外面套上一层View就可以了---下面验证以下我们的想法--
布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#00ff00" android:id="@+id/ll"> <View android:layout_width="200dp" android:layout_height="50dp" android:id="@+id/button1" android:background="#ff0000"/> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000000" android:id="@+id/fl"> <View android:layout_width="200dp" android:layout_height="50dp" android:id="@+id/button2" android:background="#0000ff"/> </FrameLayout> </LinearLayout>
这一次我在我要移动的View外部套了一个FrameLayout,然后在Activity中得到FrameLayout的引用---
public class ActivityText extends Activity implements View.OnClickListener { private View button1; private View button2; private LinearLayout ll; private FrameLayout fl; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_text); ll = (LinearLayout) findViewById(R.id.ll); fl = (FrameLayout) findViewById(R.id.fl); button1 = findViewById(R.id.button1); button2 = findViewById(R.id.button2); button1.setOnClickListener(this); } @Override public void onClick(View view) { if (view.getId() == R.id.button1) { fl.scrollBy(-30, -30); } } }
这一次在onClick事件里面我调用FrameLayout的scrollBy方法,从而达到了让第二个View移动的目的----
读者可以自己实验以下,看一下效果---
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。