Java tutorial
/* * The MIT License (MIT) * * Copyright (c) 2015 baoyongzhang <baoyz94@gmail.com> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.baoyz.dribble.widget; import android.content.Context; import android.support.v4.view.GestureDetectorCompat; import android.support.v4.view.MotionEventCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import com.baoyz.dribble.R; /** * Created by baoyz on 15/1/16. */ public class SuperRecyclerView extends RecyclerView { private OnScrollListener mScrollListener; private boolean isLoading; private WrapperAdapter mAdapter; private OnLoadMoreListener mOnLoadMoreListener; private float mDownX; private boolean mInterceptTouch; private int mTouchDistance; private float mDownY; private OnQuickScrollListener mOnQuickScrollListener; private GestureDetectorCompat mGesutureDetector; private int mFlingVelocity; public SuperRecyclerView(Context context) { this(context, null); } public SuperRecyclerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SuperRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); super.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (newState == RecyclerView.SCROLL_STATE_IDLE) { LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager(); if (layoutManager.findLastVisibleItemPosition() == (layoutManager.getItemCount() - 1)) { setLoadMore(true); } } if (mScrollListener != null) mScrollListener.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (mScrollListener != null) mScrollListener.onScrolled(recyclerView, dx, dy); } }); ViewConfiguration viewConfiguration = ViewConfiguration.get(context); mTouchDistance = viewConfiguration.getScaledOverflingDistance(); mFlingVelocity = viewConfiguration.getScaledMinimumFlingVelocity(); mGesutureDetector = new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (mOnQuickScrollListener != null && Math.abs(velocityY) > mFlingVelocity) { if (velocityY > 0) mOnQuickScrollListener.onQuickDown(); else mOnQuickScrollListener.onQuickUp(); } return super.onFling(e1, e2, velocityX, velocityY); } }); } @Override public boolean onInterceptTouchEvent(MotionEvent e) { boolean b = super.onInterceptTouchEvent(e); int actionMasked = MotionEventCompat.getActionMasked(e); switch (actionMasked) { case MotionEvent.ACTION_DOWN: mDownX = e.getX(); mDownY = e.getY(); mInterceptTouch = false; break; case MotionEvent.ACTION_MOVE: float offsetX = e.getX() - mDownX; if (!b && Math.abs(offsetX) > mTouchDistance) mInterceptTouch = true; break; } if (mInterceptTouch) return false; return b; } @Override public boolean onTouchEvent(MotionEvent e) { mGesutureDetector.onTouchEvent(e); return super.onTouchEvent(e); } public void setLoadMore(boolean load) { if (isLoading == load) return; isLoading = load; mAdapter.setFooterVisibility(isLoading ? View.VISIBLE : View.GONE); if (isLoading && mOnLoadMoreListener != null) mOnLoadMoreListener.onLoadMore(this); mAdapter.notifyDataSetChanged(); } public void setOnLoadMoreListener(OnLoadMoreListener listener) { mOnLoadMoreListener = listener; } public void setOnQuickScrollListener(OnQuickScrollListener listener) { mOnQuickScrollListener = listener; } @Override public void setOnScrollListener(OnScrollListener listener) { mScrollListener = listener; } @Override public void setAdapter(Adapter adapter) { mAdapter = new WrapperAdapter(adapter); super.setAdapter(mAdapter); } static class FooterViewHolder extends ViewHolder { View mItemView; public FooterViewHolder(View itemView) { super(itemView); mItemView = itemView; } } static class WrapperAdapter extends Adapter { public static final int TYPE_FOOTER = 0xFFFF01; private Adapter mBase; private int mFooterVisibility; public WrapperAdapter(Adapter adapter) { super(); mBase = adapter; } public void setFooterVisibility(int visibility) { mFooterVisibility = visibility; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == TYPE_FOOTER) return new FooterViewHolder( LayoutInflater.from(parent.getContext()).inflate(R.layout.footer_load, parent, false)); return mBase.onCreateViewHolder(parent, viewType); } @Override public void onBindViewHolder(ViewHolder holder, int position) { if (position == (getItemCount() - 1)) { FooterViewHolder vh = (FooterViewHolder) holder; // vh.mItemView.setVisibility(mFooterVisibility); return; } mBase.onBindViewHolder(holder, position); } @Override public int getItemViewType(int position) { if (position == (getItemCount() - 1)) return TYPE_FOOTER; return mBase.getItemViewType(position); } @Override public void setHasStableIds(boolean hasStableIds) { mBase.setHasStableIds(hasStableIds); } @Override public long getItemId(int position) { return mBase.getItemId(position); } @Override public int getItemCount() { return mBase.getItemCount() + 1; } @Override public void onViewRecycled(ViewHolder holder) { mBase.onViewRecycled(holder); } @Override public void onViewAttachedToWindow(ViewHolder holder) { mBase.onViewAttachedToWindow(holder); } @Override public void onViewDetachedFromWindow(ViewHolder holder) { mBase.onViewDetachedFromWindow(holder); } @Override public void registerAdapterDataObserver(AdapterDataObserver observer) { mBase.registerAdapterDataObserver(observer); } @Override public void unregisterAdapterDataObserver(AdapterDataObserver observer) { mBase.unregisterAdapterDataObserver(observer); } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { mBase.onAttachedToRecyclerView(recyclerView); } @Override public void onDetachedFromRecyclerView(RecyclerView recyclerView) { mBase.onDetachedFromRecyclerView(recyclerView); } } // @Override // public int getChildCount() { // return super.getChildCount() - 1; // } public static interface OnLoadMoreListener { public void onLoadMore(RecyclerView recyclerView); } public static interface OnQuickScrollListener { public void onQuickUp(); public void onQuickDown(); } }