MainActivity .class
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
@SuppressLint("NewApi")
public class MainActivity extends Activity implements OnLayoutChangeListener {
private LinearLayout layout;
private ScrollView namescroll;
private String sName = "doubi";
private final Handler mHandler = new Handler();
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout = (LinearLayout) findViewById(R.id.layout);
namescroll = (ScrollView) findViewById(R.id.nameScroll);
Log.d("...........",""+layout.getHeight());
namescroll.addOnLayoutChangeListener(this);
System.out.println("开始");
Log.d("...........",""+layout.getHeight());
for(int i = 0;i<20;i++){
searchResultShow();
System.out.println(i+"结束");
}
System.out.println(namescroll.getScrollY());
System.out.println("真正结束");
namescroll.setOnTouchListener(new OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_MOVE){
//可以监听到ScrollView的滚动事件
Toast.makeText(MainActivity.this, "sdfsdfsdf", Toast.LENGTH_SHORT).show();
}
return false;
}
});
}
private void searchResultShow() {
TextView textView = new TextView(MainActivity.this);
textView.setText("Text View ");
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
textView.setPadding(30, 15, 0, 15);
textView.setTextSize(30);
textView.setTextColor(Color.BLUE);
//增加一个TextView到线性布局中
layout.addView(textView, p);
ImageView imageView = new ImageView(MainActivity.this);
imageView.setImageResource(R.drawable.ic_launcher);
//增加一个ImageView到线性布局中
layout.addView(imageView, p);
// namescroll.addOnLayoutChangeListener(this);
}
private Runnable mScrollToBottom = new Runnable()
{
@Override
public void run()
{
int off =layout.getMeasuredHeight()-namescroll.getHeight() ;
// System.out.println(layout.getMeasuredHeight()+".........."+namescroll.getHeight() );
if (off > 0)
{
namescroll.scrollBy(0, off);
// System.out.println(" .......namescroll");
}
}
};
private Runnable ScrollRunnable= new Runnable() {
@Override
public void run() {
int off = layout.getMeasuredHeight() - namescroll.getHeight();//判断高度
System.out.println(layout.getMeasuredHeight()+".........."+namescroll.getHeight() );
if (off > 0) {
namescroll.scrollBy(0, 30);
if (namescroll.getScrollY() == off) {
Thread.currentThread().interrupt();
} else {
mHandler.postDelayed(this, 100);
}
}
}
};
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight,
int oldBottom) {
mHandler.post(ScrollRunnable);
//mHandler.post(mScrollToBottom);
//namescroll.smoothScrollBy(0, bottom);
System.out.println(bottom);
}
}
xml
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/nameScroll" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="vertical"
android:focusable="false"
android:focusableInTouchMode="false"
android:id="@+id/layout" >
</LinearLayout>
</ScrollView>
知识点小结:
view.getMeasuredHeight()可能隐藏在上头.可能在下头.如果view没有超出屏幕的时候view.getMeasuredHeight()
有可能小于 view.getHeight()getWidth(): View在設定好佈局後整個View的寬度。 getMeasuredWidth():
對View上的內容進行測量後得到的View內容佔據的寬度在一个类初始化时,即在构造函数当中是得不到View的实际大小的(这个我测试过,的确)。大家可以试试,getWidth()和getMeasuredWidth()得到的结果都是0,但是可以从onDraw()方法或者dispatchDraw()方法里面获得。可以通过调用invalidate()来执行onDraw()和dispatchDraw()方法。或者在子线程中调用
这两个方法所得到的结果的单位是像素即pixel getWidth(): View在设定好布局后,整个View的宽度 getMeasuredWidth():对View上的内容进行测量后得到的View内容占据的宽度。前提是你必须在父布局的onLayout()方法或者此View的onDraw()方法里调用measure(0,0);(measure参数的值可以知己定义),否则得到的结果和getWidth()得到的结果是一样的。
这两个方法最主要的区别在于,是否使用了measure()方法,同时measure()使用的位置也很重要。
getHeight() 和 get MeasuredHeight() 区别同理。scrollTo()和scrollBy(): scrollTo() 是直接指定滚动条的位置, 但是由于这个动作不是单纯关于
ScrollView 而已, 还要根据 ScrollView 里面包含的View 的实际信息.
所以这动作必须在页面加载完成以后才能执行. scrollBy():是滚动面介绍一下 MotionEvent 这个类
Android在MotionEvent里定义了一系列的手势事件
其中包括:
MotionEvent.ACTION_DOWN
当屏幕检测到第一个触点按下之后就会触发到这个事件MotionEvent.ACTION_MOVE
当触点在屏幕上移动时触发、触点在屏幕上停留也是会触发的、主要是由于它的灵敏度很高
而我们的手指又不可能完全静止(即使我们感觉不到移动、但其实我们的手指也在不停地抖动)MotionEvent.ACTION_POINTER_DOWN
当屏幕上已经有触点处于按下的状态的时候、再有新的触点被按下时触发MotionEvent.ACTION_POINTER_UP
当屏幕上有多个点被按住、松开其中一个点时触发(即非最后一个点被放开时)触发MotionEvent.ACTION_UP
当最后一个触点松开时被触发MotionEvent.ACTION_SCROLL
非触摸滚动、主要是由鼠标、滚轮、轨迹球触发MotionEvent.ACTION_CANCEL
不是由用户直接触发、有系统再需要的时候触发、例如当父view通过使函数onInterceptTouchEvent()返回true
从子view拿回处理事件的控制权是、就会给子view发一个ACTION_CANCEL事件
这里了view就再也不会收到事件了、可以将其视为ACTION_UP事件对待onInterceptTouchEvent()函数与onTouchEvent()的区别
1、onInterceptTouchEvent()是用于处理事件(类似于预处理、当然也可以不处理)并改变事件的传递方向
也就是决定是否允许Touch事件继续向下(子view)传递、一但返回True(代表事件在当前的viewGroup中会被处理)
则向下传递之路被截断(所有子view将没有机会参与Touch事件)同时把事件传递给当前的view的onTouchEvent()处理
返回false、则把事件交给子view的onInterceptTouchEvent()2、onTouchEvent()用于处理事件、返回值决定当前view是否消费(consume)了这个事件
也就是说在当前view在处理完Touch事件后、是否还允许Touch事件继续向上(父view)传递、一但返回True
则父view不用操心自己来处理Touch事件、返回true、则向上传递给父view(注:可能你会觉得是否消费了有关系吗
反正我已经针对事件编写了处理代码?答案是有区别!比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN
如果你没有消费ACTION_DOWN、那么系统会认为ACTION_DOWN没有发生过、所以ACTION_MOVE或者ACTION_UP就不能被捕获、)线程关闭:mHandler.removeCallbacksAndMessages(null);