博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android ListView上下滑动弹性动画
阅读量:6155 次
发布时间:2019-06-21

本文共 9653 字,大约阅读时间需要 32 分钟。

hot3.png

一、通过上拉加载下拉刷新方式实现

public class RefreshListView extends ListView implements AbsListView.OnScrollListener  {    private final String TAG ="RefreshListView";    private View mRefreshHeaderView;    private  int MAX_HEIGHT = 0;    private int mPaddingTop;    private AbsListView.OnScrollListener mOnScrollListener;    private float mLastTouchY;    private boolean isScrollAtTop;    private volatile  boolean isRefreshing;    private View mRefreshFooterView;    private int mPaddingBottom;    private boolean isScrollAtBottom;    public RefreshListView(Context context) {        this(context,null);    }    public RefreshListView(Context context, AttributeSet attrs) {        this(context, attrs,0);    }    public RefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initHeaderView();        setOnScrollListener(this);    }    private void initHeaderView() {        mRefreshHeaderView = createFooterOrHeaderView("下拉刷新");        mRefreshFooterView = createFooterOrHeaderView("加载更多");        addHeaderView(mRefreshHeaderView);        addFooterView(mRefreshFooterView);        MAX_HEIGHT = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,150,getContext().getResources().getDisplayMetrics());        final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); //宽度未指定,当然也可以设置为E(-1,EXACTLY)        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(MAX_HEIGHT, MeasureSpec.AT_MOST); //高度最大值限制为150dip        mRefreshHeaderView.measure(widthMeasureSpec,heightMeasureSpec);        mRefreshFooterView.measure(widthMeasureSpec,heightMeasureSpec);        final int headerHeight = mRefreshHeaderView.getMeasuredHeight();        mPaddingTop  = - headerHeight;        mRefreshHeaderView.setPadding(0,mPaddingTop,0,0);        final int footerHeight = mRefreshHeaderView.getMeasuredHeight();        mPaddingBottom  = - footerHeight;        mRefreshFooterView.setPadding(0,0,0,mPaddingBottom);    }    private LinearLayout createFooterOrHeaderView(String msg){        final Context context = getContext();        final DisplayMetrics metrics = context.getResources().getDisplayMetrics();        final int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP ,10,metrics );        final int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP ,40, metrics);        LinearLayout headerPanel = new LinearLayout(context);        headerPanel.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));        headerPanel.setOrientation(LinearLayout.HORIZONTAL);        headerPanel.setBackgroundColor(0x33ff0000);        headerPanel.setGravity(Gravity.CENTER);        headerPanel.setAccessibilityDelegate(new AccessibilityDelegate());        ProgressBar progressBar = new ProgressBar(context);        final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(size, size);        params.topMargin = padding;        params.bottomMargin = padding;        progressBar.setLayoutParams(params);        progressBar.setIndeterminate(true);        progressBar.setFocusable(true);        TextView tv = new TextView(context);        tv.setTextSize(12);        tv.setText(msg);        tv.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));        tv.setId(android.R.id.text1);        headerPanel.addView(progressBar);        headerPanel.addView(tv);        return headerPanel;    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        if( !isScrollAtTop &&!isScrollAtBottom || isRefreshing ) {            mLastTouchY =  ev.getY();            return super.onTouchEvent(ev);        }        switch (ev.getAction()){            case MotionEvent.ACTION_DOWN:                mLastTouchY = ev.getY();                break;            case MotionEvent.ACTION_MOVE:               startHandlePadding(ev);                break;            case MotionEvent.ACTION_UP:            case MotionEvent.ACTION_CANCEL:                 endHandlePadding(ev);                 break;        }        return super.onTouchEvent(ev);    }    private boolean endHandlePadding(MotionEvent ev) {        if(isScrollAtTop) {            float deltaY  = (ev.getY() - mLastTouchY)/2;            if (deltaY < 0) return false;            if (deltaY < (MAX_HEIGHT *3) / 5) {                mRefreshHeaderView.setPadding(0, mPaddingTop, 0, 0);            } else {                isRefreshing = true;                mRefreshHeaderView.setPadding(0, mPaddingTop + MAX_HEIGHT, 0, 0);                mRefreshHeaderView.postDelayed(finishTask, 1500);            }        }else if(isScrollAtBottom){            float deltaY  = (-ev.getY() + mLastTouchY)/2;            if (deltaY < 0) return false;            if (deltaY < (MAX_HEIGHT*3) / 5) {                mRefreshFooterView.setPadding(0, 0, 0, mPaddingBottom);            } else {                isRefreshing = true;                mRefreshFooterView.setPadding(0, 0, 0, MAX_HEIGHT + mPaddingBottom);                mRefreshFooterView.postDelayed(finishTask, 1500);            }        }        return true;    }    private boolean startHandlePadding(MotionEvent ev) {        if(isScrollAtTop) {            float deltaY = (ev.getY() - mLastTouchY)/2;// 这里 乘以 0.5作为弹性系数            if (deltaY < 0) return false;            deltaY = Math.min(deltaY, MAX_HEIGHT);            Log.d(TAG, " deltaY=" + deltaY);            mRefreshHeaderView.setPadding(0, (int) deltaY + mPaddingTop, 0, 0);            return true;        }else if(isScrollAtBottom){            float deltaY = (-ev.getY() + mLastTouchY)/2 ; // 这里 乘以 0.5作为弹性系数            if (deltaY < 0) return false;            deltaY = Math.min(deltaY, MAX_HEIGHT);            Log.d(TAG, " deltaY=" + deltaY);            mRefreshFooterView.setPadding(0, 0, 0, (int) deltaY + mPaddingBottom);            return true;        }        return false;    }    @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {        if(mOnScrollListener!=null){            mOnScrollListener.onScrollStateChanged(view,scrollState);        }    }    @Override    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {        if(mOnScrollListener!=null){            mOnScrollListener.onScroll(view,firstVisibleItem,visibleItemCount,totalItemCount);        }        isScrollAtTop = (firstVisibleItem==0);        isScrollAtBottom = (totalItemCount==(firstVisibleItem+visibleItemCount));        onDatasetChanged();    }    private final Runnable finishTask = new Runnable() {        @Override        public void run() {            isRefreshing  = false;            mRefreshHeaderView.setPadding(0, mPaddingTop, 0, 0);            mRefreshFooterView.setPadding(0, 0, 0, mPaddingBottom);        }    };    @Override    public void setAdapter(ListAdapter adapter) {        super.setAdapter(adapter);        this.onDatasetChanged();    }    private void onDatasetChanged() {        final int pos = this.getFirstVisiblePosition() + this.getHeaderViewsCount();        final ListAdapter adapter = this.getAdapter();        if(adapter==null) return;        if(pos>adapter.getCount()) return;        final String item = (String) adapter.getItem(pos);        if(TextUtils.isEmpty(item)|| item.trim().length()>1) return;    }    @Override    protected void onScrollChanged(int l, int t, int oldl, int oldt) {        super.onScrollChanged(l, t, oldl, oldt);        onDatasetChanged();    }}

二、通过重写overScrollBy实现

/** * Created by Noah on 2016/1/16. */public class BounceListView extends ListView {    private static final float MAX_Y_OVERSCROLL_DISTANCE = 200;    private float mMaxYOverscrollDistance;    public BounceListView(Context context) {        this(context, null);    }    public BounceListView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public BounceListView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initBounceListView();    }    private void initBounceListView(){        final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();        final float density = metrics.density;        mMaxYOverscrollDistance = (int) (density * MAX_Y_OVERSCROLL_DISTANCE);    }    @Override    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, (int)mMaxYOverscrollDistance, isTouchEvent);    }    /**     * 设置本App所有的ListView弹性粒度     * @param ctx     * @param size     * @return     */    public  boolean configGlobalMaxOverScrollDistance(Context ctx,int size)    {        try {            final DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();            final float density = metrics.density;            int value = (int) (density * size);            mMaxYOverscrollDistance = value;            ViewConfiguration config = ViewConfiguration.get(ctx);            Field mOverscrollDistance =  ViewConfiguration.class.getDeclaredField("mOverscrollDistance");            if(!mOverscrollDistance.isAccessible() || !Modifier.isPublic(mOverscrollDistance.getModifiers()))            {                mOverscrollDistance.setAccessible(true);            }            mOverscrollDistance.setInt(config,value);        } catch (Exception e) {            e.printStackTrace();            return false;        }        return true;    }}

 

 

转载于:https://my.oschina.net/ososchina/blog/603854

你可能感兴趣的文章
java学习:jdbc连接示例
查看>>
Silverlight 如何手动打包xap
查看>>
建筑电气暖通给排水协作流程
查看>>
linux 编码转换
查看>>
POJ-2287 Tian Ji -- The Horse Racing 贪心规则在动态规划中的应用 Or 纯贪心
查看>>
Windows8/Silverlight/WPF/WP7/HTML5周学习导读(1月7日-1月14日)
查看>>
关于C#导出 文本文件
查看>>
分享:动态库的链接和链接选项-L,-rpath-link,-rpath
查看>>
Javascript一些小细节
查看>>
禁用ViewState
查看>>
Android图片压缩(质量压缩和尺寸压缩)
查看>>
nilfs (a continuent snapshot file system) used with PostgreSQL
查看>>
【SICP练习】150 练习4.6
查看>>
HTTP缓存应用
查看>>
KubeEdge向左,K3S向右
查看>>
DTCC2013:基于网络监听数据库安全审计
查看>>
CCNA考试要点大搜集(二)
查看>>
ajax查询数据库时数据无法更新的问题
查看>>
Kickstart 无人职守安装,终于搞定了。
查看>>
linux开源万岁
查看>>