一个listview的拖动滚动效果
2014-12-22 09:24
281 查看
package com.larphoid.overscrolllistview; import android.content.Context; import android.os.Handler; import android.util.AttributeSet; import android.view.Display; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.Adapter; import android.widget.AdapterView; import android.widget.ListView; /** @author Larphoid Apps. */ public class OverscrollListview extends ListView implements OnScrollListener, View.OnTouchListener, android.widget.AdapterView.OnItemSelectedListener { protected static float BREAKSPEED = 4f, ELASTICITY = 0.67f; public int nHeaders = 1, nFooters = 1, divHeight = 0, delay = 10; private int firstVis, visibleCnt, lastVis, totalItems, scrollstate; private boolean bounce = true, rebound = false, recalcV = false, trackballEvent = false; private long flingTimestamp; private float velocity; private View measure; private GestureDetector gesture; private Handler mHandler = new Handler(); public OverscrollListview(Context context) { super(context); initialize(context); } public OverscrollListview(Context context, AttributeSet attrs) { super(context, attrs); initialize(context); } public OverscrollListview(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initialize(context); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { firstVis = firstVisibleItem; visibleCnt = visibleItemCount; totalItems = totalItemCount; lastVis = firstVisibleItem + visibleItemCount; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { scrollstate = scrollState; if ( scrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL ) { rebound = true; mHandler.postDelayed(checkListviewTopAndBottom, delay); } } @Override public void onItemSelected(AdapterView<?> av, View v, int position, long id) { rebound = true; mHandler.postDelayed(checkListviewTopAndBottom, delay); } @Override public void onNothingSelected(AdapterView<?> av) { rebound = true; mHandler.postDelayed(checkListviewTopAndBottom, delay); } @Override public boolean onTrackballEvent(MotionEvent event) { trackballEvent = true; rebound = true; mHandler.postDelayed(checkListviewTopAndBottom, delay); return super.onTrackballEvent(event); } @Override public boolean onTouch(View v, MotionEvent event) { gesture.onTouchEvent(event); return false; } private class gestureListener implements OnGestureListener { @Override public boolean onDown(MotionEvent e) { rebound = false; recalcV = false; velocity = 0f; return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { rebound = true; recalcV = true; velocity = velocityY / 25f; flingTimestamp = System.currentTimeMillis(); return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { rebound = true; recalcV = false; velocity = 0f; return false; } }; private void initialize(Context context) { final Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); final View v = new View(context); v.setMinimumHeight(Math.max(display.getWidth(), display.getHeight())); addHeaderView(v, null, false); addFooterView(v, null, false); gesture = new GestureDetector(new gestureListener()); gesture.setIsLongpressEnabled(false); flingTimestamp = System.currentTimeMillis(); setHeaderDividersEnabled(false); setFooterDividersEnabled(false); setOnTouchListener(this); setOnScrollListener(this); setOnItemSelectedListener(this); } /** This should be called after you finish populating the listview ! This includes any calls to {@link Adapter#notifyDataSetChanged()} and obviously every time you re-populate the listview. */ public void initializeValues() { nHeaders = getHeaderViewsCount(); nFooters = getFooterViewsCount(); divHeight = getDividerHeight(); firstVis = 0; visibleCnt = 0; lastVis = 0; totalItems = 0; scrollstate = 0; rebound = true; setSelectionFromTop(nHeaders, divHeight); smoothScrollBy(0, 0); mHandler.postDelayed(checkListviewTopAndBottom, delay); } /** * Turns the bouncing animation on or off. * * @param bouncing * {@code true } for bouncing effect (this is also the default), {@code false} to turn it off. */ public void setBounce(boolean bouncing) { bounce = bouncing; } /** * Sets how fast the animation will be. Higher value means faster animation. Must be >= 1.05. Together with Elasticity <= 0.75 it will not bounce forever. * * @param breakspead * Default is 4.0 */ public void setBreakspeed(final float breakspeed) { if ( Math.abs(breakspeed) >= 1.05f ) { BREAKSPEED = Math.abs(breakspeed); } } /** * Sets how much it will keep bouncing. Lower value means less bouncing. Must be <= 0.75. Together with Breakspeed >= 1.05 it will not bounce forever. * * @param elasticity * Default is 0.67 */ public void setElasticity(final float elasticity) { if ( Math.abs(elasticity) <= 0.75f ) { ELASTICITY = Math.abs(elasticity); } } public Runnable checkListviewTopAndBottom = new Runnable() { @Override public void run() { mHandler.removeCallbacks(checkListviewTopAndBottom); if ( trackballEvent && firstVis < nHeaders && lastVis >= totalItems ) { trackballEvent = false; rebound = false; return; } if ( rebound ) { if ( firstVis < nHeaders ) { // hack to avoid strange behaviour when there aren't enough items to fill the entire listview if ( lastVis >= totalItems ) { smoothScrollBy(0, 0); rebound = false; recalcV = false; velocity = 0f; } if ( recalcV ) { recalcV = false; velocity /= (1f + ((System.currentTimeMillis() - flingTimestamp) / 1000f)); } if ( firstVis == nHeaders ) { recalcV = false; } if ( visibleCnt > nHeaders ) { measure = getChildAt(nHeaders); if ( measure.getTop() + velocity < divHeight ) { velocity *= -ELASTICITY; if ( !bounce || Math.abs(velocity) < BREAKSPEED ) { rebound = false; recalcV = false; velocity = 0f; } else { setSelectionFromTop(nHeaders, divHeight + 1); } } } else { if ( velocity > 0f ) velocity = -velocity; } if ( rebound ) { smoothScrollBy((int) -velocity, 0); if ( velocity > BREAKSPEED ) { velocity *= ELASTICITY; if ( velocity < BREAKSPEED ) { rebound = false; recalcV = false; velocity = 0f; } } else velocity -= BREAKSPEED; } } else if ( lastVis >= totalItems ) { if ( recalcV ) { recalcV = false; velocity /= (1f + ((System.currentTimeMillis() - flingTimestamp) / 1000f)); } if ( lastVis == totalItems - nHeaders - nFooters ) { rebound = false; recalcV = false; velocity = 0f; } else { if ( visibleCnt > (nHeaders + nFooters) ) { measure = getChildAt(visibleCnt - nHeaders - nFooters); if ( measure.getBottom() + velocity > getHeight() - divHeight ) { velocity *= -ELASTICITY; if ( !bounce || Math.abs(velocity) < BREAKSPEED ) { rebound = false; recalcV = false; velocity = 0f; } else { setSelectionFromTop(lastVis - nHeaders - nFooters, getHeight() - divHeight - measure.getHeight() - 1); } } } else { if ( velocity < 0f ) velocity = -velocity; } } if ( rebound ) { smoothScrollBy((int) -velocity, 0); if ( velocity < -BREAKSPEED ) { velocity *= ELASTICITY; if ( velocity > -BREAKSPEED / ELASTICITY ) { rebound = false; recalcV = false; velocity = 0f; } } else velocity += BREAKSPEED; } } else if ( scrollstate == OnScrollListener.SCROLL_STATE_IDLE ) { rebound = false; recalcV = false; velocity = 0f; } mHandler.postDelayed(checkListviewTopAndBottom, delay); return; } if ( scrollstate != OnScrollListener.SCROLL_STATE_IDLE ) return; if ( totalItems == (nHeaders + nFooters) || firstVis < nHeaders ) { setSelectionFromTop(nHeaders, divHeight); smoothScrollBy(0, 0); } else if ( lastVis == totalItems ) { int offset = getHeight() - divHeight; measure = getChildAt(visibleCnt - nHeaders - nFooters); if ( measure != null ) offset -= measure.getHeight(); setSelectionFromTop(lastVis - nHeaders - nFooters, offset); smoothScrollBy(0, 0); } } }; }
https://github.com/Larphoid/android-Overscroll-ListView
使用:
android-Overscroll-ListView
An 'Overscrollable' ListView with 'Bounce' effect for android !
Usage:
The bounce effect can be turned on / off with listview.setBounce(true / false).The animation delay can be set via the delay variable, which is in milliseconds. Default = 10. The higher the value, the slower the animation.
The bounce length can be set with listview.setElasticity(float), see source file for help.
The break speed can be set with listview.setBreakspeed(float), see source file for help.
In xml, instead of creating a ListView, create a com.larphoid.overscrollinglistview.OverscrollListview
Ofcourse you can put the OverscrollListview.java in your current package and change com.larphoid.overscrollinglistview to your current package name.
When assigning the listview to a variable somewhere in your app, ofcourse you have to make it a OverscrollListview.
IMPORTANT: whenever you populate your listview, when you'r finished populating, don't forget to call listview.initializeValues().
CHANGES: after populating the listview it is not necesary anymore to set the first visible item to something other than the header or footer view (for example like this: listview.setSelectionFromTop(listview.nHeaders, listview.divHeight)), this is now done
in initializeValues().
Thats it, enjoy !
Example:
The following is an example of how to include Overscrollable in your project.package com.example.tutorial; import android.os.Bundle; import android.app.Activity; import android.widget.ArrayAdapter; import com.larphoid.overscrolllistview.OverscrollListview; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); OverscrollListview listView = (OverscrollListview)findViewById(R.id.list); // Defined Array values to show in ListView String[] values = new String[] { "List item 1", "List item 2", "List item 3", "List item 4", "List item 5", "List item 6", "List item 7", "List item 8" }; ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values); listView.setAdapter(adapter); } }
<!-- activity_main.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.larphoid.overscrolllistview.OverscrollListview android:id="@+id/list" android:layout_width="match_parent" android:layout_height="wrap_content" > </com.larphoid.overscrolllistview.OverscrollListview> </LinearLayout>
Be sure to include the 'com.larphoid.overscrolllistview' package in your Android Project src file and you're all set.
android-Overscroll-ListView
An 'Overscrollable' ListView with 'Bounce' effect for android !
Usage:
The bounce effect can be turned on / off with listview.setBounce(true / false).The animation delay can be set via the delay variable, which is in milliseconds. Default = 10. The higher the value, the slower the animation.
The bounce length can be set with listview.setElasticity(float), see source file for help.
The break speed can be set with listview.setBreakspeed(float), see source file for help.
In xml, instead of creating a ListView, create a com.larphoid.overscrollinglistview.OverscrollListview
Ofcourse you can put the OverscrollListview.java in your current package and change com.larphoid.overscrollinglistview to your current package name.
When assigning the listview to a variable somewhere in your app, ofcourse you have to make it a OverscrollListview.
IMPORTANT: whenever you populate your listview, when you'r finished populating, don't forget to call listview.initializeValues().
CHANGES: after populating the listview it is not necesary anymore to set the first visible item to something other than the header or footer view (for example like this: listview.setSelectionFromTop(listview.nHeaders, listview.divHeight)), this is now done
in initializeValues().
Thats it, enjoy !
Example:
The following is an example of how to include Overscrollable in your project.package com.example.tutorial; import android.os.Bundle; import android.app.Activity; import android.widget.ArrayAdapter; import com.larphoid.overscrolllistview.OverscrollListview; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); OverscrollListview listView = (OverscrollListview)findViewById(R.id.list); // Defined Array values to show in ListView String[] values = new String[] { "List item 1", "List item 2", "List item 3", "List item 4", "List item 5", "List item 6", "List item 7", "List item 8" }; ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values); listView.setAdapter(adapter); } }
<!-- activity_main.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.larphoid.overscrolllistview.OverscrollListview android:id="@+id/list" android:layout_width="match_parent" android:layout_height="wrap_content" > </com.larphoid.overscrolllistview.OverscrollListview> </LinearLayout>
Be sure to include the 'com.larphoid.overscrolllistview' package in your Android Project src file and you're all set.
相关文章推荐
- 一个不错的可拖动层遮罩加ALPHA滤镜(点击弹出后背景变浅色,信息提示框效果)
- 一个不错的可拖动层遮罩加ALPHA滤镜(点击弹出后背景变浅色,信息提示框效果)
- 使用ScrollView实现滚动效果 出现 ScrollView can host only one direct child (ScrollView只能包裹一个直接子元素)
- 有这样一个需求,左右各一个表格,要求拖动其中任意一个表格中的滚动条,另外一个都随之滚动,看起来就像是在一个表格中。
- 自定义ViewGroup 实现拖动跟快速滚动的效果
- 一个js实现任务栏文字滚动效果
- 拖动效果的一个实现方案
- 一个简单的行拖动效果
- 自定义ListView背景(解决了拖动变黑的效果)
- 自定义ViewGroup 实现拖动跟快速滚动的效果
- 转载:一个封装好的拖动层效果
- 仿Google的一个鼠标拖动效果(转)
- JS_拖动_一个封装好的拖动层效果
- 一个简单的行拖动效果
- 拖动效果的一个实现方案
- 一个不错的可拖动层遮罩加ALPHA滤镜(点击弹出后背景变浅色,信息提示框效果)
- 凑了一个支持拖动排序的ListView(C#)
- 给一个网友写的内容定时滚动的效果。
- 分享一个可以灵活控制的实现Javascript滚动效果的程序
- ListView,实现滚动分页效果。实现异步加载URL生成的图片。使得屏幕不卡