package me.weyye.todaynews.ui.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.OverScroller;
import com.orhanobut.logger.Logger;
import me.weyye.todaynews.R;
/**
* Created by Administrator on 2016/11/19 0019.
*/
public class PullZoomLayout extends LinearLayout {
private OverScroller mScroller;
private int mTouchSlop;
private int mMaximumVelocity;
private int mMinimumVelocity;
private View mHeaderLayout;
private View mMainLayout;
private int mScreenWidth;
private VelocityTracker mVelocityTracker;
private float mLastY;
private boolean mDragging;
private int mScreenHeight;
private LinearLayout mRootView;
private int mOverscrollDistance;
public PullZoomLayout(Context context) {
this(context, null);
}
public PullZoomLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PullZoomLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mScreenWidth = context.getResources().getDisplayMetrics().widthPixels;
mScreenHeight = context.getResources().getDisplayMetrics().heightPixels;
mScroller = new OverScroller(context);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mMaximumVelocity = ViewConfiguration.get(context)
.getScaledMaximumFlingVelocity();
mMinimumVelocity = ViewConfiguration.get(context)
.getScaledMinimumFlingVelocity();
mOverscrollDistance = ViewConfiguration.get(context).getScaledOverscrollDistance();
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.PullZoomLayout);
int headerRes = ta.getResourceId(R.styleable.PullZoomLayout_pzHeader, -1);
int mainRes = ta.getResourceId(R.styleable.PullZoomLayout_pzMain, -1);
ta.recycle();
mRootView = new LinearLayout(context);
mRootView.setOrientation(LinearLayout.VERTICAL);
mRootView.setGravity(Gravity.CENTER_HORIZONTAL);
if (headerRes == -1 || mainRes == -1) return;
// mHeaderLayout = inflate(context, headerRes, null);
// mMainLayout = inflate(context, mainRes, null);
mHeaderLayout = LayoutInflater.from(context).inflate(headerRes, mRootView, true);
mMainLayout = LayoutInflater.from(context).inflate(mainRes, mRootView, true);
// mRootView.addView(mHeaderLayout);
// mRootView.addView(mMainLayout);
addView(mRootView);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// int w = MeasureSpec.makeMeasureSpec(mRootView.getMeasuredWidth(),
// View.MeasureSpec.EXACTLY);
// int h = View.MeasureSpec.makeMeasureSpec(0,
// View.MeasureSpec.UNSPECIFIED);
//// //重新测量
// mRootView.measure(w, h);
}
@Override
protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
ViewGroup.LayoutParams lp = child.getLayoutParams();
int childWidthMeasureSpec;
int childHeightMeasureSpec;
childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, getPaddingLeft() + getPaddingRight(), lp.width);
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
@Override
protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec,
int heightUsed) {
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, getPaddingLeft() + getPaddingRight() + lp.leftMargin
+ lp.rightMargin + widthUsed, lp.width);
final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.topMargin + lp.bottomMargin, MeasureSpec.UNSPECIFIED);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(event);
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!mScroller.isFinished())
mScroller.abortAnimation();
mLastY = y;
return true;
case MotionEvent.ACTION_MOVE:
float dy = mLastY - y;
if (!mDragging && Math.abs(dy) > mTouchSlop) {
//正在准备滑动
mDragging = true;
}
if (mDragging) {
Logger.i("-dy:" + dy);
scrollBy(0, (int) dy);
}
if (dy < 0 && getScrollY() <= 0) {
//下拉
Logger.i("下拉了");
}
mLastY = y;
break;
case MotionEvent.ACTION_CANCEL:
mDragging = false;
recycleVelocityTracker();
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
break;
case MotionEvent.ACTION_UP:
mDragging = false;
mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int velocityY = (int) mVelocityTracker.getYVelocity();
if (Math.abs(velocityY) > mMinimumVelocity) {
fling(-velocityY);
}
recycleVelocityTracker();
break;
}
return super.onTouchEvent(event);
}
public void fling(int velocityY) {
mScroller.fling(0, getScrollY(), 0, velocityY, 0, 0, 0, getScrollRange());
invalidate();
}
@Override
public void scrollTo(int x, int y) {
if (y < 0) {
y = 0;
}
if (y > getScrollRange()) {
y = getScrollRange();
}
if (y != getScrollY()) {
super.scrollTo(x, y);
}
}
private int getScrollRange() {
int scrollRange = 0;
if (getChildCount() > 0) {
Logger.i("mRootView.getHeight():" + mRootView.getHeight() + "-----getHeight():" + getHeight());
scrollRange = Math.max(0,
mRootView.getHeight() - (getHeight() - getPaddingBottom() - getPaddingTop()));
}
return scrollRange;
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(0, mScroller.getCurrY());
invalidate();
}
}
private void initVelocityTrackerIfNotExists() {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
}
private void recycleVelocityTracker() {
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
}