在Android中,如何实现在一个ListView卡扣作用,同时尊重造成一扔加速? [英] In Android, how to achieve snap effect on a listview while respecting acceleration caused by fling?
问题描述
有关演示,我有一个ListView显示号码的列表。我想达到的效果,当用户滚动ListView和滚动结束,它只会在某些位置停止,以使第一个可见项目总是完全显示。我在下面附上我试图code。当用户拖拽滚动在ListView它的工作原理。但是当有猛冲,正常加速度被中断,从而导致不自然停止。我的问题是,我该怎么走引起的加速猛冲进去,同时实现同样的效果?
包com.example.snaptest;进口android.content.Context;
进口android.support.v7.app.ActionBarActivity;
进口android.os.Bundle;
进口android.view.Menu;
进口android.view.MenuItem;
进口android.view.MotionEvent;
进口android.view.View;
进口android.view.ViewGroup;
进口android.widget.AbsListView;
进口android.widget.BaseAdapter;
进口android.widget.LinearLayout;
进口android.widget.ListView;
进口android.widget.TextView;
公共类MainActivity扩展ActionBarActivity { 私有静态类TestListViewAdapter延伸BaseAdapter { 私人语境mContext; 公共TestListViewAdapter(上下文的背景下){
mContext =背景;
} @覆盖
公众诠释的getCount(){
返回100;
} @覆盖
公共对象的getItem(INT位置){
返回Integer.toString(位置);
} @覆盖
众长getItemId(INT位置){
返回的位置;
} @覆盖
公共查看getView(INT位置,查看convertView,父母的ViewGroup){
TextView中的TextView =新的TextView(mContext);
textView.setText(Integer.toString(位置));
AbsListView.LayoutParams PARAMS =新AbsListView.LayoutParams(ViewGroup.LayoutParams
.MATCH_PARENT,180);
textView.setLayoutParams(PARAMS);
返回的TextView;
}
} 私有静态类TestListView扩展的ListView { 公共TestListView(上下文的背景下){
超级(上下文);
} @覆盖
公共布尔onTouchEvent(MotionEvent EV){
如果(ev.getAction()== MotionEvent.ACTION_UP || ev.getAction()== MotionEvent.ACTION_CANCEL){
视图ItemView控件= getChildAt(0);
INT顶= Math.abs(itemView.getTop()); //顶部为负值
INT底部= Math.abs(itemView.getBottom());
如果(顶部> =底部){
smoothScrollToPositionFromTop
(getFirstVisiblePosition()+ 1,0);
}其他{
smoothScrollToPositionFromTop
(getFirstVisiblePosition(),0);
}
}
返回super.onTouchEvent(EV);
} } @覆盖
保护无效的onCreate(捆绑savedInstanceState){
super.onCreate(savedInstanceState);
TestListView的ListView =新TestListView(本);
listView.setAdapter(新TestListViewAdapter(本));
的setContentView(ListView控件);
}}
我会尝试用 OnScrollListener
而不是扩展的ListView
。
事情是这样的:
listView.setOnScrollListener(新AbsListView.OnScrollListener(){
@覆盖
公共无效onScrollStateChanged(AbsListView观点,诠释scrollState){
如果(scrollState == AbsListView.SCROLL_STATE_IDLE){
//根据顶端对齐列表视图/底部项的知名度
}
} @覆盖
公共无效onScroll(AbsListView观点,诠释firstVisibleItem,诠释visibleItemCount,诠释totalItemCount){
}
});
For demonstration, I have a ListView displaying a list of numbers. I would like to achieve the effect that when the user scrolls the ListView and the scrolling ends, it will only stop at certain positions so that the first visible item is always shown completely. I've attached my attempted code below. It works when users drag to scroll the ListView. But when there's fling, the normal acceleration is interrupted, causing an unnatural stop. My question is, how can I take acceleration caused by fling into account while achieving the same effect?
package com.example.snaptest;
import android.content.Context;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
private static class TestListViewAdapter extends BaseAdapter {
private Context mContext;
public TestListViewAdapter(Context context) {
mContext = context;
}
@Override
public int getCount() {
return 100;
}
@Override
public Object getItem(int position) {
return Integer.toString(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView = new TextView(mContext);
textView.setText(Integer.toString(position));
AbsListView.LayoutParams params = new AbsListView.LayoutParams(ViewGroup.LayoutParams
.MATCH_PARENT, 180);
textView.setLayoutParams(params);
return textView;
}
}
private static class TestListView extends ListView {
public TestListView(Context context) {
super(context);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
View itemView = getChildAt(0);
int top = Math.abs(itemView.getTop()); // top is a negative value
int bottom = Math.abs(itemView.getBottom());
if (top >= bottom){
smoothScrollToPositionFromTop
(getFirstVisiblePosition() + 1, 0);
} else {
smoothScrollToPositionFromTop
(getFirstVisiblePosition(), 0);
}
}
return super.onTouchEvent(ev);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TestListView listView = new TestListView(this);
listView.setAdapter(new TestListViewAdapter(this));
setContentView(listView);
}
}
I would try with an OnScrollListener
rather than extending ListView
.
Something like this:
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == AbsListView.SCROLL_STATE_IDLE) {
// snap the listview according to the top/bottom items' visibility
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
这篇关于在Android中,如何实现在一个ListView卡扣作用,同时尊重造成一扔加速?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!