一个listview的拖动滚动效果_mlistview滚动效果怎么写-程序员宅基地

技术标签: 滚动特效  android  listview  ANDROID  

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.

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/a332324956/article/details/42076185

智能推荐

关于Linux下root密码的问题-程序员宅基地

文章浏览阅读95次。 这几天看到一个同学进不去他的Linux下的root权限,su root的时候让他敲root的密码他自己都不知道。貌似这个密码是当时装Linux的时候设的,如果自己当时不设一下的话,系统就会自动给随机一个密码给你。据说是为了安全性。那他怎么获得他的root权限呢?sudo固然可以短暂获得,但那终究是扬汤止沸。下面介绍一下做法。sudo passwd root 然后输入自己的密码,...

openstack调整实例大小_openstack 调整实例大小-程序员宅基地

文章浏览阅读1.8k次,点赞2次,收藏11次。新建实例类型2C-4G-20G修改controller和各个computer节点的nova.cnf文件vim /etc/nova/nova.conf[DEFAULT]allow_resize_to_same_host=Truescheduler_default_filters=RetryFilter,AvailabilityZoneFilter,RamFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,Serv_openstack 调整实例大小

java笔试面试总结_java 笔试减少去同一地方的次数-程序员宅基地

文章浏览阅读382次。java笔试面试总结java基础基础多线程虚拟机数据库Spring网络dubbojava基础基础Object类常用的方法有哪些?wait:final方法,无法被重写。作用:阻塞当前线程,且当前线程必须拥有此对象的monitor(即锁)notify:final方法,无法被重写。作用:唤醒一个正在等待该对象monitor的线程。如果有多个线程都在等待该对象的monitor,只唤醒一个n..._java 笔试减少去同一地方的次数

STP,RSTP,MSTP学习_mstp 名词定义 bid pid-程序员宅基地

文章浏览阅读666次。转载至华为官方技术文档,只做笔记参考,不作它用。定义以太网交换网络中为了进行链路备份,提高网络可靠性,通常会使用冗余链路。但是使用冗余链路会在交换网络上产生环路,引发广播风暴以及MAC地址表不稳定等故障现象,从而导致用户通信质量较差,甚至通信中断。为解决交换网络中的环路问题,提出生成树协议STP(Spanning Tree Protocol)。与众多协议的发展过程一样,生成树协议也是随着网..._mstp 名词定义 bid pid

Centos7.4网卡配置_centos7.4配置网卡-程序员宅基地

文章浏览阅读1.2k次。Centos7.4网卡配置1、Linux操作系统安装完毕,那接下来如何让Linux操作系统能上外网呢?如下为Linux服务器配置IP的方法。Linux服务器网卡默认配置文件在/etc/sysconfig/network-scripts/下,命名的名称一般为:ifcfg-eth0 ifcfg-eth1 ,eth0表示第一块网卡,eth1表示第二块网卡,依次类推。修改服务器网卡IP地址命令为vi /etc/sysconfig/network-scripts/ifcfg-eth0 (注CentOS7网卡名i_centos7.4配置网卡

windows curl 之 invalid character ‘\‘‘ looking for beginning of value_urllib content:{"describe":"invalid character 'p' -程序员宅基地

文章浏览阅读1.4k次,点赞3次,收藏3次。windows terminal 执行 curl 报 invalid character '\" looking for beginning of value_urllib content:{"describe":"invalid character 'p' looking for beginning of v

随便推点

有n个人围成一圈,顺序排号。从第一个人开始报号(从1到3报数),凡报到3的的人退出圈子,问最后留下的是原来第几号的那位。_编写程序,有n个人围成一圈,顺序编号,从第一个人开始按1、2、3顺序报数,凡报 到3的-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏4次。题目有n个人围成一圈,顺序排号。从第一个人开始报号(从1到3报数),凡报到3的的人退出圈子,问最后留下的是原来第几号的那位。思路解题关键:凡报到3的人就应该退出圈子,当有n-1个人退出圈子时剩下的那个人就是最后留下的人。解题思路:创建一个数组num[n],数组num[n]赋值从1开始到n。申请一个变量k当满足条件k=3时,第i个人退出圈子(退出圈子时num[i]-0)申请一个变量m代表..._编写程序,有n个人围成一圈,顺序编号,从第一个人开始按1、2、3顺序报数,凡报 到3的

Android加载H5页面——webView加载网页时图片不显示_android webview无法加载图片-程序员宅基地

文章浏览阅读3.8k次,点赞3次,收藏8次。WebView加载网页,图片不显示直接上效果图:在Android studio中加载URL链接的时候,有些图片可以显示,有些显示不出来;考虑可以有以下原因:android webview 从Lollipop(5.0)开始webview默认不允许混合模式,https当中不能加载http资源,而开发的时候可能使用的是https的链接,但是链接中的图片可能是http的,所以需要设置开启。解..._android webview无法加载图片

几种基本汇编指令详解_movq-程序员宅基地

文章浏览阅读4.3w次,点赞29次,收藏138次。几种基本汇编指令详解常见寄存器 寄存器 16位 32位 64位 累加寄存器 AX EAX RAX 基址寄存器 BX EBX RBX 计数寄存器 CX ECX RCX 数据寄存器 DX EDX RDX 堆栈基指针 BP EBP RBP 变址寄存器 SI ESI RSI 堆栈顶指针 SP_movq

u8、u16、u32、s8、s16、s32、Size_t是什么类型?_u8就是char-程序员宅基地

文章浏览阅读10w+次,点赞51次,收藏330次。1.u8就是unsigned char ,是8位无符号char类型的值/*!&lt; Signed integer types */typedef signed char int8_t;typedef signed short int16_t;typedef signed long int32_t;/*!&lt; Unsigned integer..._u8就是char

freeswitch mrcp 源码分析--数据接收(下)_freeswitch 对接腾讯云mrcp-程序员宅基地

文章浏览阅读3.3k次。在前两篇我们介绍了mrcp接收后的处理,最后会调用apr_queue_push扔到消息队列里面。 对应的,在apt_consumer_task.apt_consumer_task_run()中会循环调用pr_queue.apr_queue_pop()从队列里面取出数据:apt_consumer_task.apt_consumer_task_run –> apr_queue.apr_queue_p_freeswitch 对接腾讯云mrcp

数据库SQLite常用语句<三>_sqlite数据库 in 语句-程序员宅基地

文章浏览阅读335次。**一、数据库表的操作:** 1. 创建数据库表创建数据库:create table 表名( _id integer primary key autoincrement,//主键id自增长 name varchar(40), age integer(20), birthday datetime //最后一行不用写 逗号(,)_sqlite数据库 in 语句