編輯:關於Android編程
用scrollTo()和scrollBy()方法實現了View的滑動,但是實現的效果非常的生硬,用戶體驗很差。
這一篇繼續在原有基礎上,擴展下View的彈性滑動。下面詳細介紹下實現Viiew彈性滑動的幾種方式。
我們可以使用Scroller這個類來實現View內容的彈性滑動,使用起來也很簡單,只需三步:
第一步:創建Scroller對象。Scroller mScroller = new Scroller(context);第二步:調用startScroll()方法。
mScroller.startScroll(getScrollX(), getScrollY() , -50, -50); invalidate();第三步:重寫View的computeScroll()方法,實現具體滑動邏輯。
@Override public void computeScroll() { if(mScroller.computeScrollOffset()){ scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } }
下面以一個簡單的例子演示下Scroller這個類的用法:
首先自定義一個LinearLayout,並在構造中創建了Scroller對象,提供了一個startScroll()方法,並且重寫了computeScroll()方法:
/** * 作者:周游 * 時間:2016/11/13 * 博客:http://blog.csdn.net/airsaid */ public class ScrollerLinearLayout extends LinearLayout{ private final Scroller mScroller; public ScrollerLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); mScroller = new Scroller(context); } public void startScroll(){ mScroller.startScroll(getScrollX(), getScrollY() , -50, -50); invalidate(); } @Override public void computeScroll() { if(mScroller.computeScrollOffset()){ scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } } }
在布局中用該自定義LinearLayout包裹了一個Button:
在代碼中調用了其startScroll()方法:
public class MainActivity extends AppCompatActivity { private ScrollerLinearLayout mLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLayout = (ScrollerLinearLayout) findViewById(R.id.layout); } public void start(View v){ mLayout.startScroll(); } }
運行結果:
通過上面的例子,簡單實現了用Scroller實現了View的彈性滑動。但是這一切都是怎麼一個過程呢?首先來看看Scroller的startScroll()方法:
public void startScroll(int startX, int startY, int dx, int dy, int duration) { mMode = SCROLL_MODE; mFinished = false; mDuration = duration; mStartTime = AnimationUtils.currentAnimationTimeMillis(); mStartX = startX; mStartY = startY; mFinalX = startX + dx; mFinalY = startY + dy; mDeltaX = dx; mDeltaY = dy; mDurationReciprocal = 1.0f / (float) mDuration; }
通過查看startScroll()方法的源碼可以發現,其內部只是做了賦值的操作,並沒有調用其他的方法,那麼這個彈性滑動的效果又是從哪裡來的呢?
答案就在於,我們在調用startScroll()方法後又調用了invalidate()方法使View進行了重繪。那麼這時就會走View的draw方法,在View的draw方法中又會去調用View的computeScroll()方法,而該方法在View中是一個空實現。這就解釋了我們為什麼需要復寫computeScroll()方法。
在computeScroll()方法中,我們調用了computeScrollOffset()方法進行判斷,該方法內部會根據時間的流逝來計算出scrollX和scrollY改變的百分比並計算出當前的值。這個方法的返回值也很重要,返回true表示滑動還未結束,false表示滑動已經結束。所以在這裡,我們進行了判斷,當其返回true時,就調用scrollTo()方法使View滑動,並調用invalidate()重繪,只要滑動沒有完成就繼續遞歸下去。
到這裡Scroller的工作原理就很清晰了,Scroller並不能單獨完成View的彈性滑動,而是要配合View的computeScroll()方法,不斷的通過invalidate()方法重繪View,計算Scroller的X和Y值,並通過scrollTo()方法一點點的移動,連在一起,就形成了彈性滑動。
使用動畫使View實現滑動效果,其本身就具有彈性滑動的效果。所以只要掌握了動畫的使用,那麼就可以輕松實現出View的彈性滑動效果。
除了上面的幾種實現方式之外,我們還可以使用延時策略。延時策略就是通過發送一系列的延時消息從而達到一種漸進式的效果。我們可以使用Handler的postDelayed方法,也可以使用其他的延遲消息方法。這裡我們就用Handler來實現一個簡單的彈性滑動效果:
rivate int mStartX = 0; Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case 0: if(mStartX > -100){ mLayout.scrollTo(mStartX, 0); mStartX --; mHandler.sendEmptyMessageDelayed(0, 5); } break; } } };
點擊按鈕時,發送延時消息:
mHandler.sendEmptyMessageDelayed(0, 5);
運行結果:
通過了解以上幾種實現彈性滑動的方法,知道了可以用Scroller實現View內的彈性滑動,使用動畫可以實現View的彈性滑動。
在這幾種方式中,其實更重要的是實現思想。只要掌握了其思想,那麼就可以靈活運用起來,實現更多復雜的效果。
自動完成文本框(AutoCompleteTextView)java.lang.Object;android.view.View;android.view.TextView
三種得到LinearInflater的方法a. LayoutInflater inflater = getLayoutInflater();b. LayoutInflat
Android WebView常見問題解決方案匯總:就目前而言,如何應對版本的頻繁更新呢,又如何靈活多變地展示我們的界面呢,這又涉及到了web app與native ap
在了解系統的activity,service,broadcastReceiver的啟動過程後,今天將分析下360 DroidPlugin是如何預注冊占坑的?本篇文章主要分