一个listview的拖动滚动效果

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值