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

android 带漂浮tab菜单 StickyNavLayout

2016-12-24 17:09 197 查看
主要控制滑动事件的分配(仅支持listview,pulltorefreshlist和ScrollView)

public class StickyNavLayout extends LinearLayout implements NestedScrollingParent
{
private static final String TAG = "StickyNavLayout";

@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes)
{
Log.e(TAG, "onStartNestedScroll");
return true;
}

@Override
public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes)
{
Log.e(TAG, "onNestedScrollAccepted");
}

@Override
public void onStopNestedScroll(View target)
{
Log.e(TAG, "onStopNestedScroll");
}

@Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed)
{
Log.e(TAG, "onNestedScroll");
}

@Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed)
{
Log.e(TAG, "onNestedPreScroll");
boolean hiddenTop = dy > 0 && getScrollY() < mTopViewHeight;
boolean showTop = dy < 0 && getScrollY() >= 0 && !ViewCompat.canScrollVertically(target, -1);

if (hiddenTop || showTop)
{
scrollBy(0, dy);
consumed[1] = dy;
}
}

@Override
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed)
{
Log.e(TAG, "onNestedFling");
return false;
}

@Override
public boolean onNestedPreFling(View target, float velocityX, float velocityY)
{
Log.e(TAG, "onNestedPreFling");
//down - //up+
if (getScrollY() >= mTopViewHeight) return false;
fling((int) velocityY);
return true;
}

@Override
public int getNestedScrollAxes()
{
Log.e(TAG, "getNestedScrollAxes");
return 0;
}

private View mTop;
private View mNav;
private ViewPager mViewPager;

private int mTopViewHeight;

private OverScroller mScroller;
private VelocityTracker mVelocityTracker;
private int mTouchSlop;
private int mMaximumVelocity, mMinimumVelocity;

private float mLastY;
private boolean mDragging;

public StickyNavLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
setOrientation(LinearLayout.VERTICAL);

mScroller = new OverScroller(context);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mMaximumVelocity = ViewConfiguration.get(context)
.getScaledMaximumFlingVelocity();
mMinimumVelocity = ViewConfiguration.get(context)
.getScaledMinimumFlingVelocity();

}

private void initVelocityTrackerIfNotExists()
{
if (mVelocityTracker == null)
{
mVelocityTracker = VelocityTracker.obtain();
}
}

private void recycleVelocityTracker()
{
if (mVelocityTracker != null)
{
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(event);
int action = event.getAction();
float y = event.getY();

switch (action)
{
case MotionEvent.ACTION_DOWN:
if (!mScroller.isFinished())
mScroller.abortAnimation();
mLastY = y;
return true;
case MotionEvent.ACTION_MOVE:
float dy = y - mLastY;

if (!mDragging && Math.abs(dy) > mTouchSlop)
{
mDragging = true;
}
if (mDragging)
{
scrollBy(0, (int) -dy);
}

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);
}

@Override
protected void onFinishInflate()
{
super.onFinishInflate();
mTop = findViewById(R.id.id_stickynavlayout_topview);
mNav = findViewById(R.id.id_stickynavlayout_indicator);
View view = findViewById(R.id.id_stickynavlayout_viewpager);
if (!(view instanceof ViewPager))
{
throw new RuntimeException(
"id_stickynavlayout_viewpager show used by ViewPager !");
}
mViewPager = (ViewPager) view;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
//不限制顶部的高度
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
getChildAt(0).measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
ViewGroup.LayoutParams params = mViewPager.getLayoutParams();
params.height = getMeasuredHeight() - mNav.getMeasuredHeight();
setMeasuredDimension(getMeasuredWidth(), mTop.getMeasuredHeight() + mNav.getMeasuredHeight() + mViewPager.getMeasuredHeight());

}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mTopViewHeight = mTop.getMeasuredHeight();
}

public void fling(int velocityY)
{
mScroller.fling(0, getScrollY(), 0, velocityY, 0, 0, 0, mTopViewHeight);
invalidate();
}

@Override
public void scrollTo(int x, int y)
{
if (y < 0)
{
y = 0;
}
if (y > mTopViewHeight)
{
y = mTopViewHeight;
}
if (y != getScrollY())
{
super.scrollTo(x, y);
}
isTopHidden = getScrollY() == mTopViewHeight;
}

@Override
public void computeScroll()
{
if (mScroller.computeScrollOffset())
{
scrollTo(0, mScroller.getCurrY());
invalidate();
}
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int action = ev.getAction();
float y = ev.getY();

switch (action) {
case Motion
fefb
Event.ACTION_DOWN:
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
float dy = y - mLastY;
getCurrentScrollView();

if (mInnerScrollView instanceof ScrollView) {
if (mInnerScrollView.getScrollY() == 0 && isTopHidden && dy > 0
&& !isInControl) {
isInControl = true;
ev.setAction(MotionEvent.ACTION_CANCEL);
MotionEvent ev2 = MotionEvent.obtain(ev);
dispatchTouchEvent(ev);
ev2.setAction(MotionEvent.ACTION_DOWN);
return dispatchTouchEvent(ev2);
}
} else if (mInnerScrollView instanceof ListView) {

ListView lv = (ListView) mInnerScrollView;
View c = lv.getChildAt(lv.getFirstVisiblePosition());

if (!isInControl && c != null && c.getTop() == 0 && isTopHidden
&& dy > 0) {
isInControl = true;
ev.setAction(MotionEvent.ACTION_CANCEL);
MotionEvent ev2 = MotionEvent.obtain(ev);
dispatchTouchEvent(ev);
ev2.setAction(MotionEvent.ACTION_DOWN);
return dispatchTouchEvent(ev2);
}
}else if (mInnerScrollView instanceof PullToRefreshListView) {
ListView lv =  ((PullToRefreshListView) mInnerScrollView).getRefreshableView();
View c = lv.getChildAt(lv.getFirstVisiblePosition());

if (!isInControl && c != null && c.getTop() == 0 && isTopHidden
&& dy > 0) {
isInControl = true;
ev.setAction(MotionEvent.ACTION_CANCEL);
MotionEvent ev2 = MotionEvent.obtain(ev);
dispatchTouchEvent(ev);
ev2.setAction(MotionEvent.ACTION_DOWN);
return dispatchTouchEvent(ev2);
}
}
break;
}
return super.dispatchTouchEvent(ev);
}

/**
*
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
float dy = y - mLastY;
getCurrentScrollView();
if (Math.abs(dy) > mTouchSlop) {
mDragging = true;
if (mInnerScrollView instanceof ScrollView) {
// 如果topView没有隐藏
// 或sc的scrollY = 0 && topView隐藏 && 下拉,则拦截
if (!isTopHidden
|| (mInnerScrollView.getScrollY() == 0
&& isTopHidden && dy > 0)) {

initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
mLastY = y;
return true;
}
} else if (mInnerScrollView instanceof ListView) {

ListView lv = (ListView) mInnerScrollView;
View c = lv.getChildAt(lv.getFirstVisiblePosition());
// 如果topView没有隐藏
// 或sc的listView在顶部 && topView隐藏 && 下拉,则拦截

if (!isTopHidden || c==null||//
(c != null //
&& c.getTop() == 0//
&& isTopHidden && dy > 0)) {

initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
mLastY = y;
Log.d(TAG,"onInterceptTouchEvent: true");
return true;
}
}else if (mInnerScrollView instanceof PullToRefreshListView) {

ListView lv = ((PullToRefreshListView) mInnerScrollView).getRefreshableView();
View c = lv.getChildAt(lv.getFirstVisiblePosition());
// 如果topView没有隐藏
// 或sc的listView在顶部 && topView隐藏 && 下拉,则拦截

if (!isTopHidden || c==null||//
(c != null //
&& c.getTop() == 0//
&& isTopHidden && dy > 0)) {

initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
mLastY = y;
Log.d(TAG,"onInterceptTouchEvent: true");
return true;
}
}

}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mDragging = false;
recycleVelocityTracker();
break;
}
Log.d(TAG,"onInterceptTouchEvent:"+super.onInterceptTouchEvent(ev)+"");
return super.onInterceptTouchEvent(ev);
}

private ViewGroup mInnerScrollView;
private boolean isTopHidden = false;
private boolean isInControl = false;

private void getCurrentScrollView() {

int currentItem = mViewPager.getCurrentItem();
PagerAdapter a = mViewPager.getAdapter();
if (a instanceof FragmentPagerAdapter) {
FragmentPagerAdapter fadapter = (FragmentPagerAdapter) a;
Fragment item = (Fragment) fadapter.instantiateItem(mViewPager,
currentItem);
mInnerScrollView = (ViewGroup) (item.getView()
.findViewById(R.id.id_stickynavlayout_innerscrollview));
} else if (a instanceof FragmentStatePagerAdapter) {
FragmentStatePagerAdapter fsAdapter = (FragmentStatePagerAdapter) a;
Fragment item = (Fragment) fsAdapter.instantiateItem(mViewPager,
currentItem);
mInnerScrollView = (ViewGroup) (item.getView()
.findViewById(R.id.id_stickynavlayout_innerscrollview));
}

}

}

tab菜单栏

public class SimpleViewPagerIndicator extends LinearLayout
{

private static final int COLOR_TEXT_NORMAL = 0xFF000000;
private static final int COLOR_INDICATOR_COLOR = Color.GREEN;

private String[] mTitles;
private int mTabCount;
private int mIndicatorColor = COLOR_INDICATOR_COLOR;
private float mTranslationX;
private Paint mPaint = new Paint();
private int mTabWidth;

public SimpleViewPagerIndicator(Context context)
{
this(context, null);
}

public SimpleViewPagerIndicator(Context context, AttributeSet attrs)
{
super(context, attrs);
mPaint.setColor(mIndicatorColor);
mPaint.setStrokeWidth(9.0F);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mTabWidth = w / mTabCount;
}

public void setTitles(String[] titles)
{
mTitles = titles;
mTabCount = titles.length;
generateTitleView();

}

public void setIndicatorColor(int indicatorColor)
{
this.mIndicatorColor = indicatorColor;
}

private OnPagerSelected mOnPagerSelected;

public void setOnPagerSelected(OnPagerSelected listener){
mOnPagerSelected=listener;
}

public interface OnPagerSelected{
void onPagerSelected(int position);
}

@Override
protected void dispatchDraw(Canvas canvas)
{
super.dispatchDraw(canvas);
canvas.save();
canvas.translate(mTranslationX, getHeight() - 2);
canvas.drawLine(0, 0, mTabWidth, 0, mPaint);
canvas.restore();
}

public void scroll(int position, float offset)
{
/**
* <pre>
*  0-1:position=0 ;1-0:postion=0;
* </pre>
*/
mTranslationX = getWidth() / mTabCount * (position + offset);
invalidate();
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
return super.dispatchTouchEvent(ev);
}

private void generateTitleView()
{
if (getChildCount() > 0)
this.removeAllViews();
int count = mTitles.length;

setWeightSum(count);
for (int i = 0; i < count; i++)
{
TextView tv = new TextView(getContext());
LayoutParams lp = new LayoutParams(0,
LayoutParams.MATCH_PARENT);
lp.weight = 1;
tv.setGravity(Gravity.CENTER);
tv.setTextColor(COLOR_TEXT_NORMAL);
tv.setText(mTitles[i]);
tv.setTag(i);
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
tv.setLayoutParams(lp);
tv.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
if(mOnPagerSelected!=null){
mOnPagerSelected.onPagerSelected((int) v.getTag());
}
}
});
addView(tv);
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: