在Android中,如何实现在一个ListView卡扣作用,同时尊重造成一扔加速? [英] In Android, how to achieve snap effect on a listview while respecting acceleration caused by fling?

查看:103
本文介绍了在Android中,如何实现在一个ListView卡扣作用,同时尊重造成一扔加速?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有关演示,我有一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆