效果图:
项目结构:
代码:
MainActivity
package com.example.scrolltest; import android.app.Activity; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; /* 1. 瞬间移动视图的内容: 利用View的scroll方法 1). scrollBy(int x, int y) : 滑动指定的偏移量(从当前位置瞬间) x: x轴上的偏移量, x>0内容向左滑动, x<0内容向右滑动, x=0水平方向不滑动 y: y轴上的偏移量, y>0内容向上滑动, y<0内容向下滑动, y=0垂直方向不滑动 2). scrollTo(int x, int y) : 滑动到指定的偏移量(从当前位置瞬间) x: 目标位置x轴上的偏移量, x>0移动到原始位置的左侧, x<0移动到原始位置的右侧,x=0移动到水平原始位置, y: 目标位置y轴上的偏移量, y>0移动到原始位置的上侧, y<0移动到原始位置的下侧, y=0移动到垂直原始位置 2. 平滑移动视图的内容: 利用Scoller和View的scroll方法 1). Scoller是实现View平滑移动的帮助类, 它本身并不能实现对View的移动 2). 平滑移动的基本原理: 将整个从起始位置到结束位置的移动分解成多个小的距离, 循环调用scrollTo()实现平滑移动 3). 相关API: a. Scoller类: -->Scoller(Context context) : 创建对象的构造方法 -->startScroll(int startX, int startY, int dx, int dy, int duration) : 开始平滑移动视图(这个方法本身不会产生滑动) startX : 起始位置的X偏移量 startY : 起始位置的Y偏移量 dx: 滑动多大的X偏移量(如果是0,X方向不会滑动) dy: 滑动多大的Y偏移量(如果是0,Y方向不会滑动) duration : 整个过程持续的时间(ms) -->startScroll(int startX, int startY, int dx, int dy): 开始平滑移动视图(时间为250ms) -->boolean computeScrollOffset() : 计算当前移动的偏移量, 并将其保存到Scoller对象中, 如果滑动还没有完成返回true -->int getCurrX() : 得到计算出的X偏移量 -->int getCurrY() : 得到计算出的Y偏移量 b. View类 -->invalidate() : 强制重绘, 导致draw()-->computeScroll() 在scoller.startScroll()后必须执行此方法 -->computeScroll() : 需要重写此方法, 用于计算移动, 此方法在draw()中调用 调用scoller计算移动偏移量 调用view对象scrollTo()到计算出的偏移量 调用View对象invalidate()强制重绘, 导致computeScroll()再次执行 */ // 对应视频 // http://www.gulixueyuan.com/course/124/learn#lesson/1910 // scrollBy的使用 public class MainActivity extends Activity { private Button btnScrollLeft; private Button btnScrollRight; private Button btnScrollUp; private Button btnScrollDown; private Button btnReset1; private Button btnReset2; private MyImageView ivMain; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); myOnclick(); } private void myOnclick() { btnScrollLeft.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ivMain.scrollBy(10, 0); Log.e("TAG", ivMain.getScrollX() + "-"); } }); btnScrollRight.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ivMain.scrollBy(-10, 0); Log.e("TAG", ivMain.getScrollX() + "-"); } }); btnScrollUp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ivMain.scrollBy(0, 10); Log.e("TAG", ivMain.getScrollX() + "-"); } }); btnScrollDown.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ivMain.scrollBy(0, -10); Log.e("TAG", ivMain.getScrollX() + "-"); } }); btnReset1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ivMain.scrollTo(0, 0); } }); btnReset2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ivMain.reset(); } }); } private void initView() { btnScrollLeft = (Button)findViewById( R.id.btnScrollLeft ); btnScrollRight = (Button)findViewById( R.id.btnScrollRight ); btnScrollUp = (Button)findViewById( R.id.btnScrollUp ); btnScrollDown = (Button)findViewById( R.id.btnScrollDown ); btnReset1 = (Button)findViewById(R.id.btnReset1); btnReset2 = (Button)findViewById( R.id.btnReset2 ); ivMain = (MyImageView)findViewById( R.id.ivMain ); } }
自动以控件MyImageViewpackage com.example.scrolltest; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.ImageView; import android.widget.Scroller; import android.widget.Toast; import com.orhanobut.logger.Logger; public class MyImageView extends ImageView { // 开始坐标 private float startX; private Scroller scroller; // 图片宽高 private int myWidth; // 距离左边的距离 private int slideLeft; // 画笔 Paint paint; // 位图 Bitmap slidingBitmap; // 上下文 Context context; public MyImageView(Context context, AttributeSet attrs) { super(context, attrs); this.context=context; scroller = new Scroller(context); paint = new Paint(); //设置抗锯齿,就是图像边缘平滑 paint.setAntiAlias(true); // 图片 slidingBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); // 设置位图大小 slidingBitmap = Bitmap.createScaledBitmap(slidingBitmap, 600, 600, true); } public void reset() { scroller.startScroll(getScrollX(), getScrollY(), -getScrollX(), -getScrollY(), 1000); invalidate(); } @Override public void computeScroll() { if(scroller.computeScrollOffset()) {//滑动还没有完成 Log.e("TAG", "CurrX="+scroller.getCurrX()); scrollTo(scroller.getCurrX(), scroller.getCurrY()); invalidate(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); myWidth=600; Logger.t("111").d("width>>>"+myWidth); // 设置宽高 setMeasuredDimension(600, 600); } /** * onTouchEvent * 点击事件 * 滑动 * 触摸都在这里完成 */ @Override public boolean onTouchEvent(MotionEvent event) { Log.d("111","onTouchEvent"); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: startX = event.getX(); Log.d("111","MotionEvent.ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: // 调用这两个方法,感受两种滑动的不同 move1(event); // move2(event); break; case MotionEvent.ACTION_UP: Log.d("111","MotionEvent.ACTION_UP"); break; } return true; } /** * 使用scrollTo实现滑动 */ private void move1(MotionEvent event){ Log.d("111","MotionEvent.ACTION_MOVE"); float endX = event.getX(); // 偏移量 float distanceX = endX- startX; // 坐标 int toScrollX= (int) (getScrollX()-distanceX); // 设置移动范围 if(toScrollX<0) { toScrollX=0; }else if(toScrollX>myWidth) { toScrollX=myWidth; } scrollTo(toScrollX,0); } /** *绘制实现滑动 */ private void move2(MotionEvent event){ // 移动一次ACTION_MOVE要执行很多次 Logger.t("666").d("ACTION_MOVE>>>"); //2.计算结束值 float endX = event.getX(); //3.计算偏移量 float distanceX = endX - startX; // slideLeft = (int) (slideLeft + distanceX); slideLeft += distanceX; //4.屏蔽非法值 Logger.t("777").d("distanceX>>>"+distanceX+"endX>>>"+endX+"startX>>>"+startX); Logger.t("777").d("距左边的距离>>>"+slideLeft); if(slideLeft <0){ slideLeft = 0; }else if(slideLeft>myWidth){ slideLeft = myWidth; } //5.刷新,就只重新绘制 invalidate(); //6.数据还原(执行了很多周期的初始值向223.11,224.22......) startX = event.getX(); } /** * 绘制 * @param canvas */ @Override protected void onDraw(Canvas canvas) { // super.onDraw(canvas); // 上面的滑动按钮 canvas.drawBitmap(slidingBitmap, slideLeft, 0, paint); } }
activity_main.xml中
参考视频:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_horizontal" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <Button android:id="@+id/btnScrollLeft" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="左移scrollBy(10, 0)" /> <Button android:id="@+id/btnScrollRight" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="右移scrollBy(-10, 0)" /> <Button android:id="@+id/btnScrollUp" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="上移scrollBy(0, 10)" /> <Button android:id="@+id/btnScrollDown" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="下移scrollBy(0, -10)" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <Button android:id="@+id/btnReset1" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="瞬间复位scrollTo(0, 0)" /> <Button android:id="@+id/btnReset2" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="平滑复位View.reset()" /> </LinearLayout> <com.example.scrolltest.MyImageView android:id="@+id/ivMain" android:layout_width="200dp" android:layout_height="200dp" android:background="#ff0000" android:src="@drawable/ic_launcher" /> </LinearLayout>
http://www.gulixueyuan.com/course/124/learn#lesson/1910
源码下载:Myself----scrolltesthttp://download.csdn.net/download/zhaihaohao1/10111351