您的位置:首页 > 移动开发 > Android开发

Android自定义控件——PullZoomView

2016-03-18 14:09 387 查看
本文介绍PullZoomView的简单实现,如图:



就是通过下拉ListView或者ScrollView或者更多的View如GridView,RecycleView等等,的时候对Header有一个放大缩小的效果

实现思路就是根据所需要封装的不同的下拉控件来做不同的实现,比如:

ListView:该控件本身有添加Header的功能,我们只需做简单的处理就可以用了,在满足一定条件时做事件拦截,让整个控件向下滚动的时候回传一个value用来改变Header的高度。

ScrollView:这就需要我们自己封装一个Header在ScrollView的孩子控件当中。滚动的时候和ListView做相同的操作即可。



IPullZoom                               定义公共接口

PullZoomBase                         抽象公共的方法

PullZoomListView                  ListView的实现

PullZoomScrollView              ScrollView的实现

IPullZoom.java

[java]
view plain
copy





public interface IPullZoom {  
  
    void initHeader(TypedArray a);  
}  

PullZoomBase.java

[java]
view plain
copy





public abstract class PullZoomBase<T extends View> extends LinearLayout implements IPullZoom {  
    /** 
     * 根布局,用来装所有内容 
     */  
    protected T mRootView;  
    /** 
     * 定义的显示伸缩效果的View 
     */  
    protected View mZoomView;  
    /** 
     * 伸缩效果上展示的内容 
     */  
    protected View mHeadView;  
    /** 
     * 是否允许下拉 
     */  
    private boolean isPullEnable = true;  
  
    private boolean isZooming;  
  
    private boolean isHeadHide;  
  
    private boolean isDragging;  
  
    private float mLastX;  
  
    private float mLastY;  
  
    private float mInitX;  
  
    private float mInitY;  
  
    private int mTouchSlop;  
  
    public PullZoomBase(Context context) {  
        this(context, null);  
    }  
  
    public PullZoomBase(Context context, AttributeSet attrs) {  
        this(context, attrs, 0);  
    }  
  
    public PullZoomBase(Context contex
4000
t, AttributeSet attrs, int defStyleAttr) {  
        super(context, attrs, defStyleAttr);  
        ViewConfiguration config = ViewConfiguration.get(context);  
        mTouchSlop = config.getScaledTouchSlop();  
        mRootView = initRootView(context, attrs);  
        LayoutInflater inflater = LayoutInflater.from(context);  
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PullZoomView);  
        int zoomResId = a.getResourceId(R.styleable.PullZoomView_zoomview, 0);  
        if (zoomResId > 0) {  
            mZoomView = inflater.inflate(zoomResId, null, false);  
        }  
        int headResId = a.getResourceId(R.styleable.PullZoomView_headview, 0);  
        if (headResId > 0) {  
            mHeadView = inflater.inflate(headResId, null, false);  
        }  
        initHeader(a);  
        a.recycle();  
        addView(mRootView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);  
    }  
  
    @Override  
    public boolean onInterceptTouchEvent(MotionEvent ev) {  
        if (!isPullEnable() || isHeadHide()) {  
            return false;  
        }  
        int action = ev.getAction();  
        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {  
            isDragging = false;  
            return false;  
        }  
        if (action != MotionEvent.ACTION_DOWN && isDragging) {  
            return true;  
        }  
        switch (action) {  
            case MotionEvent.ACTION_DOWN:  
                if (allowStart()) {  
                    mLastX = mInitX = ev.getX();  
                    mLastY = mInitY = ev.getY();  
                    isDragging = false;  
                }  
                break;  
            case MotionEvent.ACTION_MOVE:  
                if (allowStart()) {  
                    float x = ev.getX();  
                    float y = ev.getY();  
                    float diffX = x - mLastX;  
                    float diffY = y - mLastY;  
                    float diffYAds = Math.abs(diffY);  
                    if (diffYAds > mTouchSlop && diffYAds > Math.abs(diffX)) {  
                        if (diffY >= 1 && allowStart()) {  
                            mLastX = x;  
                            mLastY = y;  
                            isDragging = true;  
                        }  
                    }  
                }  
                break;  
        }  
        return isDragging;  
  
    }  
  
    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
        if (!isPullEnable || isHeadHide()) {  
            return false;  
        }  
        if (event.getAction() == MotionEvent.ACTION_DOWN && event.getEdgeFlags() != 0) {  
            return false;  
        }  
        switch (event.getAction()) {  
            case MotionEvent.ACTION_DOWN:  
                if (allowStart()) {  
                    mLastX = mInitX = event.getX();  
                    mLastY = mInitY = event.getY();  
                    return true;  
                }  
                break;  
            case MotionEvent.ACTION_MOVE:  
                if (allowStart()) {  
                    mLastX = event.getX();  
                    mLastY = event.getY();  
                    final int newScrollValue = Math.round(Math.min(mInitY - mLastY, 0) / 2.0f);  
                    pull(newScrollValue);  
                    return true;  
                }  
                break;  
            case MotionEvent.ACTION_UP:  
            case MotionEvent.ACTION_CANCEL:  
                if (isDragging) {  
                    isDragging = false;  
                    smoothRestore();  
                }  
                break;  
        }  
        return false;  
    }  
  
    public boolean isPullEnable() {  
        return isPullEnable;  
    }  
  
    public void setIsPullEnable(boolean isPullEnable) {  
        this.isPullEnable = isPullEnable;  
    }  
  
    public boolean isHeadHide() {  
        return isHeadHide;  
    }  
  
    public void setIsHeadHide(boolean isHeadHide) {  
        this.isHeadHide = isHeadHide;  
    }  
  
  
    /** 
     * 创建根布局,例如ListView,GridView,RecycleView,ScrollView等等 
     * 
     * @param context 
     * @param set 
     * @return 
     */  
    public abstract T initRootView(Context context, AttributeSet set);  
  
    /** 
     * 判定是否允许开始滚动 
     * 
     * @return 
     */  
    public abstract boolean allowStart();  
  
    /** 
     * 传入一个计算值,用来对Header做放大缩小操作 
     * 
     * @param value 
     */  
    public abstract void pull(int value);  
  
    /** 
     * 
     */  
    public abstract void smoothRestore();  
  
  
}  

PullZoomListView.java

[java]
view plain
copy





public class PullZoomListView extends PullZoomBase<ListView> {  
  
    private FrameLayout mHeaderContainer;  
  
    private int mHeaderHeight;  
  
    private SmoothRestore mSmoothRestore;  
  
    public static Interpolator mInterpolator = new Interpolator() {  
        @Override  
        public float getInterpolation(float input) {  
            float f = input - 1.0F;  
            return 1.0F + f * (f * (f * (f * f)));  
        }  
    };  
  
    public PullZoomListView(Context context) {  
        this(context, null);  
    }  
  
    public PullZoomListView(Context context, AttributeSet attrs) {  
        this(context, attrs, 0);  
    }  
  
    public PullZoomListView(Context context, AttributeSet attrs, int defStyleAttr) {  
        super(context, attrs, defStyleAttr);  
        mSmoothRestore = new SmoothRestore();  
    }  
  
    @Override  
    public ListView initRootView(Context context, AttributeSet set) {  
        ListView listview = new ListView(context, set);  
        return listview;  
    }  
  
    @Override  
    public void initHeader(TypedArray a) {  
        mHeaderContainer = new FrameLayout(getContext());  
        if (mZoomView != null) {  
            mHeaderContainer.addView(mZoomView);  
        }  
        if (mHeadView != null) {  
            mHeaderContainer.addView(mHeadView);  
        }  
        mRootView.addHeaderView(mHeaderContainer);  
    }  
  
    public void setAdapter(BaseAdapter adapter) {  
        mRootView.setAdapter(adapter);  
    }  
  
    public void setHeaderLayoutParams(AbsListView.LayoutParams params) {  
        if (mHeaderContainer != null) {  
            mHeaderContainer.setLayoutParams(params);  
            mHeaderHeight = params.height;  
        }  
    }  
  
    public void updateHeader() {  
        if (mHeaderContainer != null) {  
            mRootView.removeHeaderView(mHeaderContainer);  
            mHeaderContainer.removeAllViews();  
            if (mZoomView != null) {  
                mHeaderContainer.addView(mZoomView);  
            }  
            if (mHeadView != null) {  
                mHeaderContainer.addView(mHeadView);  
            }  
            mHeaderHeight = mHeaderContainer.getHeight();  
            mRootView.addHeaderView(mHeaderContainer);  
        }  
    }  
  
    @Override  
    public boolean allowStart() {  
        return isFirstItemVisiable();  
    }  
  
    private boolean isFirstItemVisiable() {  
        Adapter adapter = mRootView.getAdapter();  
        if (null == adapter || adapter.isEmpty()) {  
            return true;  
        } else {  
            if (mRootView.getFirstVisiblePosition() <= 1) {  
                View view = mRootView.getChildAt(0);  
                if (view != null) {  
                    return view.getTop() >= mRootView.getTop();  
                }  
            }  
        }  
        return false;  
    }  
  
    @Override  
    public void pull(int value) {  
        if (mSmoothRestore != null && !mSmoothRestore.isFinish()) {  
            mSmoothRestore.abort();  
        }  
        ViewGroup.LayoutParams params = mHeaderContainer.getLayoutParams();  
        params.height = Math.abs(value) + mHeaderHeight;  
        mHeaderContainer.setLayoutParams(params);  
    }  
  
    @Override  
    public void smoothRestore() {  
        mSmoothRestore.start(200L);  
    }  
  
    class SmoothRestore implements Runnable {  
        protected long duration;  
        protected boolean isFinished;  
        protected float scale;  
        protected long starttime;  
  
        SmoothRestore() {  
        }  
  
        public void abort() {  
            isFinished = true;  
        }  
  
        public boolean isFinish() {  
            return isFinished;  
        }  
  
        public void start(long d) {  
            if (mZoomView != null) {  
                starttime = SystemClock.currentThreadTimeMillis();  
                duration = d;  
                scale = (float) mHeaderContainer.getBottom() / mHeaderHeight;  
                isFinished = false;  
                post(this);  
            }  
        }  
  
        @Override  
        public void run() {  
            if (mZoomView != null) {  
                float f2;  
                ViewGroup.LayoutParams params;  
  
                if (!isFinished && scale > 1.0D) {  
                    float f1 = ((float) SystemClock.currentThreadTimeMillis() - (float) starttime) / (float) duration;  
                    f2 = scale - (scale - 1.0F) * PullZoomListView.mInterpolator.getInterpolation(f1);  
                    params = mHeaderContainer.getLayoutParams();  
                    if (f2 > 1.0F) {  
                        params.height = (int) (f2 * mHeaderHeight);  
                        mHeaderContainer.setLayoutParams(params);  
                        post(this);  
                        return;  
                    }  
                    isFinished = true;  
                }  
  
            }  
        }  
    }  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: