scrollview,Android Scroller的使用及自我理解

 2023-10-30 阅读 26 评论 0

摘要:2019獨角獸企業重金招聘Python工程師標準>>> ? 以前做一個看書的項目時,有個翻書的功能,當手指滑動書頁移動一段然后抬起后,需要頁面view自動完成剩余的操作:1、當滑動距離大于某個設定值時,自動滾動到末尾處,翻一頁。2、

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

? 以前做一個看書的項目時,有個翻書的功能,當手指滑動書頁移動一段然后抬起后,需要頁面view自動完成剩余的操作:
1、當滑動距離大于某個設定值時,自動滾動到末尾處,翻一頁。
2、當滑動距離小于該設定值時,自動回滾到起始處,還原。
? 實現這個功能,當時是用了Scroller來實現的,由于自己還是菜鳥,搞了老久沒懂,最近看android時,猛然發現,原來是這樣啊。

? 我一步步來說下吧:

1、Scroller的最簡單用法解釋

? 網上有很多關于Scroller的用法,很多講的真的很不錯,但我覺得,他們的講解還是過于繁瑣,這里我就最最簡單的說下吧,這個Scroller到底怎么回事,且看下面代碼:

scrollview、 ? ?下面的這個demo1,就一個布局,linearlayout上放置一個button,點擊button,我們就調用Scroller的相關方法:

布局文件xml:

<LinearLayout 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:orientation="vertical" ><Buttonandroid:id="@+id/button1"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignLeft="@+id/textView1"android:layout_margin="10dp"android:text="run  Scroller " />
</LinearLayout>
控制器activity:

package cn.helloclq.nb.scroller;import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.Scroller;public class MainActivity extends Activity {private Scroller mScroller;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mScroller = new Scroller(this);this.setContentView(R.layout.activity_main);	findViewById(R.id.button1).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mScroller.startScroll(-10, -100,- 200, -300, 1000);new Thread(){public void run() {while(mScroller.computeScrollOffset())// 如果mScroller沒有調用startScroll,這里將會返回false。{Log.i("scroller", "getCurrX()= "+mScroller.getCurrX()+"     getCurrY()="+mScroller.getCurrY());try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}}};}.start();}});}
}
運行后,點擊按鈕,就可以看到效果,且看控制臺日志輸出:

android cursor、

05-02 11:30:55.455: I/scroller(30287): getCurrX()= -10     getCurrY()=-100
05-02 11:30:55.510: I/scroller(30287): getCurrX()= -26     getCurrY()=-124
05-02 11:30:55.557: I/scroller(30287): getCurrX()= -63     getCurrY()=-180
05-02 11:30:55.612: I/scroller(30287): getCurrX()= -111     getCurrY()=-251
05-02 11:30:55.658: I/scroller(30287): getCurrX()= -144     getCurrY()=-301
05-02 11:30:55.713: I/scroller(30287): getCurrX()= -166     getCurrY()=-334
05-02 11:30:55.760: I/scroller(30287): getCurrX()= -181     getCurrY()=-356
05-02 11:30:55.815: I/scroller(30287): getCurrX()= -191     getCurrY()=-371
05-02 11:30:55.862: I/scroller(30287): getCurrX()= -197     getCurrY()=-381
05-02 11:30:55.916: I/scroller(30287): getCurrX()= -201     getCurrY()=-387
05-02 11:30:55.963: I/scroller(30287): getCurrX()= -204     getCurrY()=-391
05-02 11:30:56.018: I/scroller(30287): getCurrX()= -206     getCurrY()=-394
05-02 11:30:56.065: I/scroller(30287): getCurrX()= -208     getCurrY()=-396
05-02 11:30:56.119: I/scroller(30287): getCurrX()= -208     getCurrY()=-398
05-02 11:30:56.166: I/scroller(30287): getCurrX()= -209     getCurrY()=-398
05-02 11:30:56.221: I/scroller(30287): getCurrX()= -209     getCurrY()=-399
05-02 11:30:56.268: I/scroller(30287): getCurrX()= -210     getCurrY()=-399
05-02 11:30:56.322: I/scroller(30287): getCurrX()= -210     getCurrY()=-400
05-02 11:30:56.369: I/scroller(30287): getCurrX()= -210     getCurrY()=-400
05-02 11:30:56.424: I/scroller(30287): getCurrX()= -210     getCurrY()=-400
05-02 11:30:56.471: I/scroller(30287): getCurrX()= -210     getCurrY()=-400
從日志輸出的數據一看,你應該能大致知道這個scroller的作用了吧

mScroller.startScroll(-10, -100,- 200, -300, 1000);
我們在button的事件處理里做的是調用了   public void?startScroll?(int startX, int startY, int dx, int dy,int?duration)?

這個方法,然后我們在線程中一直查看scroller的幾個屬性數值,然后打印了出來,從日志可以看出,scroller中的這些數值,是按(int startX, int startY, int dx, int dy)來變化的,并且是在intduration這個時間段內完成的。我們設置線程的睡眠時間是50毫秒,而打印了總共20條日志,20* 50 = 1000,正好是我們設置的這個時間

? 如果我們在調用了public void?startScroll?(int startX, int startY, int dx, int dy,in tduration) ?,讓我們的view重新繪制,并且利用scroller的幾個屬性數值來確定view的位置或其他的什么,然后不斷的循環調用,你說會出現什么呢?答案就不用說了吧(view會動起來吧),這個就是我們平時在項目中利用scroller的主要思路了,而一般的時候,我們會多繞了幾道彎兒而已。

對自我的理解? 2、Scroller結合view的用法

? 首先,我們簡單的介紹下view,查看android的源碼,你會發現如下的方法:

/**
* Called by a parent to request that a child update its values for mScrollX
* and mScrollY if necessary. This will typically be done if the child is
* animating a scroll using a {@link android.widget.Scroller Scroller}
* object.
*/
public void computeScroll()
{
}
該方法就是留給我們去覆寫的,它一般都會被該view的父類viewGroup在繪制該view時調用,具體的,就不多說了,大家可以參見相關博客,如果我們在這個方法里,調用 scroller的相關屬性來修改view的相關屬性或調用其他方法,是不是可以做很多事呢?

? 下面看看改造后的demo2:

先介紹一個函數,view下面的:

Android,

public void scrollTo (int x, int y) Added in API level 1
Set the scrolled position of your view. This will cause a call to onScrollChanged(int, int, int, int) and the view will be invalidated.Parameters
x	the x position to scroll to
y	the y position to scroll to
該函數可以使view中的內容滾動到指定位置:

demo2:

該demo沒有xml,直接就一個activity:

package cn.helloclq.nb.scroller;import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Scroller;public class MainActivity extends Activity {LinearLayout demoSubview1, demoSubview2, demoViewGroup;private Scroller mScrollerViewGroup;private Scroller mScrollerView;
//	private Scroller mScroller;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mScrollerViewGroup = new Scroller(this);mScrollerView = new Scroller(this);demoSubview1 = new DemoView(this);demoSubview2 = new DemoView(this);demoSubview1.setBackgroundColor(this.getResources().getColor(android.R.color.darker_gray));demoSubview2.setBackgroundColor(this.getResources().getColor(android.R.color.white));demoViewGroup = new DemoViewGroup(this);demoViewGroup.setOrientation(LinearLayout.VERTICAL);LinearLayout.LayoutParams p0 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);this.setContentView(demoViewGroup, p0);LinearLayout.LayoutParams p1 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);p1.weight = 1;demoViewGroup.addView(demoSubview1, p1);LinearLayout.LayoutParams p2 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);p2.weight = 1;demoViewGroup.addView(demoSubview2, p2);DemoButton btn1 = new DemoButton(this);btn1.setText("run  Scroller in viewGroup");btn1.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mScrollerViewGroup.startScroll(-10, -100,- 200, -300, 1000);new Thread(){public void run() {while(mScrollerViewGroup.computeScrollOffset())// 如果mScroller沒有調用startScroll,這里將會返回false。{Log.i("scroller", "getCurrX()= "+mScrollerViewGroup.getCurrX()+"     getCurrY()="+mScrollerViewGroup.getCurrY());try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}}};}.start();}});demoSubview1.addView(btn1);DemoButton btn2 = new DemoButton(this);btn2.setText("run  Scroller in view");btn2.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mScrollerView.startScroll(-10, -100,- 200, -300, 1000);new Thread(){public void run() {while(mScrollerView.computeScrollOffset())// 如果mScroller沒有調用startScroll,這里將會返回false。{Log.i("scroller", "getCurrX()= "+mScrollerView.getCurrX()+"     getCurrY()="+mScrollerView.getCurrY());try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}}};}.start();}});demoSubview2.addView(btn2);}class DemoButton extends Button {public DemoButton(Context ctx) {super(ctx);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Log.i("DemoButton",  "------ onDraw------");}public void computeScroll() {Log.i("DemoButton", " --------------------computeScroll-----------");//	Log.i(TAG, "getCurrX = " + mScroller.getCurrX());if (mScrollerView.computeScrollOffset())// 如果mScroller沒有調用startScroll,這里將會返回false。{// 因為調用computeScroll函數的是MyLinearLayout實例,// 所以調用scrollTo移動的將是該實例的孩子,也就是MyButton實例scrollTo(mScrollerView.getCurrX(), 0);Log.i("DemoButton", "getCurrX = " + mScrollerView.getCurrX());// 繼續讓系統重繪invalidate();}}}class DemoView extends LinearLayout {public DemoView(Context ctx) {super(ctx);}@Overridepublic void computeScroll() {Log.i("DemoView", " DemoView --------------------computeScroll-----------");if (mScrollerViewGroup.computeScrollOffset())// 如果mScroller沒有調用startScroll,這里將會返回false。{// 因為調用computeScroll函數的是MyLinearLayout實例,// 所以調用scrollTo移動的將是該實例的孩子,也就是MyButton實例scrollTo(mScrollerViewGroup.getCurrX(), 0);Log.i("DemoView", "getCurrX = " + mScrollerViewGroup.getCurrX());// 繼續讓系統重繪getChildAt(0).invalidate();}}}class DemoViewGroup extends LinearLayout {public DemoViewGroup(Context ctx) {super(ctx);}@Overrideprotected void dispatchDraw(Canvas canvas) {Log.i("DemoViewGroup", "contentview dispatchDraw");super.dispatchDraw(canvas);}}
}
運行程序效果:

Android使用自帶文件?

點擊第一個button后,日志如下:

05-02 13:38:02.291: I/DemoViewGroup(332): contentview dispatchDraw
05-02 13:38:02.291: I/DemoView(332):  DemoView --------------------computeScroll------
05-02 13:38:02.301: I/DemoButton(332):  --------------------computeScroll-----------
05-02 13:38:02.311: I/DemoButton(332): ------ onDraw------
05-02 13:38:02.311: I/DemoView(332):  DemoView --------------------computeScroll------
05-02 13:38:02.311: I/DemoButton(332):  --------------------computeScroll-----------
05-02 13:38:02.311: I/DemoButton(332): ------ onDraw------
05-02 13:39:50.432: I/scroller(332): getCurrX()= -11     getCurrY()=-101 05-02 13:39:50.432: I/DemoViewGroup(332): contentview dispatchDraw
05-02 13:39:50.432: I/DemoView(332):  DemoView --------------------computeScroll------
05-02 13:39:50.432: I/DemoView(332): getCurrX = -12
05-02 13:39:50.442: I/DemoButton(332):  --------------------computeScroll-----------
05-02 13:39:50.442: I/DemoButton(332): ------ onDraw------
......................此處省略部分日志...................................................
05-02 13:39:51.412: I/DemoViewGroup(332): contentview dispatchDraw
05-02 13:39:51.412: I/DemoView(332):  DemoView --------------------computeScroll------
05-02 13:39:51.412: I/DemoView(332): getCurrX = -210
05-02 13:39:51.412: I/DemoButton(332):  --------------------computeScroll-----------
05-02 13:39:51.422: I/DemoButton(332): ------ onDraw------
05-02 13:39:51.432: I/DemoViewGroup(332): contentview dispatchDraw
05-02 13:39:51.432: I/DemoView(332):  DemoView --------------------computeScroll------
05-02 13:39:51.432: I/DemoButton(332):  --------------------computeScroll-----------
05-02 13:39:51.432: I/DemoButton(332): ------ onDraw------
通過日志,看出什么了沒?

另外,通過該日志,你了解了view的繪畫機制沒,應該能發現吧。

最終的效果圖片:

您正在使用Android,


點擊buttom2,日志就不給出了,效果圖片如下:

button內的文字移動到了不可見處,

所以調用scrollTo移動的將是該view的內容,如果是viewGroup的話,就移動了它的孩子view了

scrollview怎么用?

所以調用scrollTo移動的將是該實例的孩子,也就是MyButton實例

這會兒明白了沒?

后面我會嘗試的自己模擬一個scrolelr,其實他的作用就是存儲一些基本的數值,其他的啥也沒做,也和view沒有真正關系的,它只是被動的被調用的

轉載于:https://my.oschina.net/chengliqun/blog/126935

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/4/164627.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息