一、效果图
二、总体布局xml文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/ll_headinfo"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_alignParentTop="true"
android:background="@color/black_333333"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="头部导航"
android:textColor="@color/white" />
</LinearLayout>
<com.example.yangdechengapplication.scrollview.StickyScrollViewList
android:id="@+id/sticky_scroll_view_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/ll_headinfo"
android:focusable="true"
android:focusableInTouchMode="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="80dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#b18f8f"
android:gravity="center"
android:text="这里可以无限添加顶部内容"
android:textColor="#000000"
android:textSize="20sp" />
</RelativeLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"></View>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:tag="sticky">
<android.support.design.widget.TabLayout
android:id="@+id/tabs_order"
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="@color/white"
app:tabIndicatorColor="#F23A3A"
app:tabIndicatorHeight="3dp"
app:tabMinWidth="80dp"
app:tabMode="scrollable"
app:tabSelectedTextColor="#F23A3A"
app:tabTextColor="#333333" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"></View>
<com.example.yangdechengapplication.scrollview.CustomViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:visibility="visible" />
<LinearLayout
android:id="@+id/ll_bottom_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="20dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="这里可以无限添加底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#89a66f"
android:text="底部内容"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="10dp" />
</LinearLayout>
</LinearLayout>
</com.example.yangdechengapplication.scrollview.StickyScrollViewList>
<LinearLayout
android:id="@+id/ll_bottom_bar"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:background="@color/black_333333"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="底部导航"
android:textColor="@color/white" />
</LinearLayout>
</RelativeLayout>
三、StickyScrollViewActivity类
package com.example.yangdechengapplication.scrollview;
import android.app.Activity;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LayoutAnimationController;
import com.example.yangdechengapplication.R;
import java.util.ArrayList;
import java.util.List;
/**
* Created by decheng.yang on 2017/10/26.
*/
public class StickyScrollViewActivity extends FragmentActivity implements StickyScrollViewList.OnScrollChangedListener, StickyScrollViewList.IOnScrollToEnd {
private StickyScrollViewList mStickyScrollViewList;
private TabLayout tabsOrder;
private List<Fragment> fragmentList;
private String[] titles;
private CustomViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stickyscrollview);
mStickyScrollViewList = (StickyScrollViewList) findViewById(R.id.sticky_scroll_view_list);
mStickyScrollViewList.setOnScrollListener(this);
mStickyScrollViewList.setOnScrollToEndListener(this);
tabsOrder = (TabLayout) findViewById(R.id.tabs_order);
viewPager = (CustomViewPager) findViewById(R.id.viewPager);
initMemu();
}
private void initMemu() {
titles = new String[4];
titles[0] = "昆明";
titles[1] = "北京";
titles[2] = "上海";
titles[3] = "深圳";
fragmentList = getChildFragmentList(titles);
MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), fragmentList, titles, StickyScrollViewActivity.this);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(titles.length);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
viewPager.resetHeight(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
viewPager.resetHeight(0);
//viewPager.setPageTransformer(true, new ZoomOutPageTransformer());
//viewPager.setPageTransformer(true, new DepthPageTransformer());
//TabLayout
//TabLayout tabLayout = (TabLayout)findViewById(R.id.tabLayout);
tabsOrder.setupWithViewPager(viewPager);
tabsOrder.setTabMode(TabLayout.MODE_SCROLLABLE);
/* Animation animation = (Animation) AnimationUtils.loadAnimation(StickyScrollViewActivity.this, R.anim.fade_in);
LayoutAnimationController lac = new LayoutAnimationController(animation);
lac.setOrder(LayoutAnimationController.ORDER_NORMAL);
lac.setDelay(0.5f);
tabsOrder.setLayoutAnimation(lac);*/
}
private List<Fragment> getChildFragmentList(String[] titles) {
List<Fragment> fragmentList = new ArrayList<>();
for (int i = 0; i < titles.length; i++) {
Bundle bundle = new Bundle();
String s = "";
if (i == 0 || i == 3) {
s = "我是菜单" + i + "的内容啊\n第一条 注意物资的种类和标识,不能因搬运\n" +
"第二条 尽量使用搬运工具;";
} else if (i == 1) {
s = "我是菜单" + i + "的内容啊\n第一条 注意物资的种类和标识,不能因搬运\n" +
"第二条 尽量使用搬运工具;\n" +
"第三条 注意人身和物资安全;\n" +
"第四条 注意物资的种类和标识,不能因搬运而使物资混乱不清,注意人身和物资安全;";
} else if (i == 2) {
s = "我是菜单" + i + "的内容啊\n第一条 注意物资的种类和标识,不能因搬运\n" +
"第二条 尽量使用搬运工具;\n" +
"第三条 注意人身和物资安全;\n" +
"第四条 注意物资的种类和标识,不能因搬运而使物资混乱不清,注意人身和物资安全; \"第三条 注意人身和物资安全;\\n\" +\n" +
" \"第四条 注意物资的种类和标识,不能因搬运而使物资混乱不清,注意人身和物资安全; \"第三条 注意人身和物资安全;\\n\" +\n" +
" \"第四条 注意物资的种类和标识,不能因搬运而使物资混乱不清,注意人身和物资安全;";
}
bundle.putString("content", s);
bundle.putInt("position", i);
TabLayoutFragment orderDetailRemarkFragment = new TabLayoutFragment();
orderDetailRemarkFragment.setArguments(bundle);
fragmentList.add(orderDetailRemarkFragment);
orderDetailRemarkFragment.setCustomViewPager(this.viewPager);
}
return fragmentList;
}
@Override
public void onScrollChanged(int l, int t, int oldl, int oldt) {
}
@Override
public void onScrollToEnd() {
}
}
四、CustomViewPager类
package com.example.yangdechengapplication.scrollview;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import java.util.HashMap;
import java.util.LinkedHashMap;
/**
* Created by decheng.yang on 2017/10/30.
*/
public class CustomViewPager extends ViewPager {
private int current;
private int height = 0;
/**
* 保存position与对于的View
*/
private HashMap<Integer, View> mChildrenViews = new LinkedHashMap<Integer, View>();
private boolean scrollble = true;
public CustomViewPager(Context context) {
super(context);
}
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mChildrenViews.size() > current) {
View child = mChildrenViews.get(current);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
height = child.getMeasuredHeight();
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void resetHeight(int current) {
this.current = current;
if (mChildrenViews.size() > current) {
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
if (layoutParams == null) {
layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, height);
} else {
layoutParams.height = height;
}
setLayoutParams(layoutParams);
}
}
/**
* 保存position与对于的View
*/
public void setObjectForPosition(View view, int position) {
mChildrenViews.put(position, view);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (!scrollble) {
return true;
}
return super.onTouchEvent(ev);
}
public boolean isScrollble() {
return scrollble;
}
public void setScrollble(boolean scrollble) {
this.scrollble = scrollble;
}
}
五、MyFragmentPagerAdapter类
package com.example.yangdechengapplication.scrollview;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.ArrayList;
import java.util.List;
/**
* Created by decheng.yang on 2017/10/13.
*/
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
private String[] titles;
//public final int COUNT = titles.length;
private List<Fragment> fragmentList = new ArrayList<>();
private Context context;
public MyFragmentPagerAdapter(FragmentManager fm, List<Fragment> fragmentList, String[] titles, Context context) {
super(fm);
this.context = context;
this.fragmentList = fragmentList;
this.titles = titles;
}
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList.size();
}
@Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
}
六、StickyScrollViewList类
package com.example.yangdechengapplication.scrollview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.widget.ScrollView;
import com.example.yangdechengapplication.R;
import java.util.ArrayList;
public class StickyScrollViewList extends ScrollView {
/**
* Tag for views that should stick and have constant drawing. e.g.
* TextViews, ImageViews etc
*/
public static final String STICKY_TAG = "sticky";
/**
* Flag for views that should stick and have non-constant drawing. e.g.
* Buttons, ProgressBars etc
*/
public static final String FLAG_NONCONSTANT = "-nonconstant";
/**
* Flag for views that have aren't fully opaque
*/
public static final String FLAG_HASTRANSPARANCY = "-hastransparancy";
/**
* Default height of the shadow peeking out below the stuck view.
*/
private static final int DEFAULT_SHADOW_HEIGHT = 10; // dp;
/**
* XKJ add for add 50dp offset of top
*/
private static final int MIN_STICK_TOP = 0;// px
// private static final int MIN_STICK_TOP = 0;
private ArrayList<View> stickyViews;
private View currentlyStickingView;
private float stickyViewTopOffset;
private int stickyViewLeftOffset;
private boolean redirectTouchesToStickyView;
private boolean clippingToPadding;
private boolean clipToPaddingHasBeenSet;
private int mShadowHeight;
private Drawable mShadowDrawable;
private OnScrollChangedListener mOnScrollHandler = null;
private IOnScrollToEnd mOnScrollToEnd = null;
private IOnScroollToTop mOnScrollToTop = null;
private final Runnable invalidateRunnable = new Runnable() {
@Override
public void run() {
if (currentlyStickingView != null) {
int l = getLeftForViewRelativeOnlyChild(currentlyStickingView);
int t = getBottomForViewRelativeOnlyChild(currentlyStickingView);
int r = getRightForViewRelativeOnlyChild(currentlyStickingView);
int b = (int) (getScrollY() + (currentlyStickingView.getHeight() +
stickyViewTopOffset));
invalidate(l, t, r, b);
}
postDelayed(this, 16);
}
};
public StickyScrollViewList(Context context) {
this(context, null);
}
public StickyScrollViewList(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.scrollViewStyle);
}
public StickyScrollViewList(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StickyScrollView,
defStyle, 0);
final float density = context.getResources().getDisplayMetrics().density;
int defaultShadowHeightInPix = (int) (DEFAULT_SHADOW_HEIGHT * density + 0.5f);
mShadowHeight = a.getDimensionPixelSize(R.styleable.StickyScrollView_stuckShadowHeight,
defaultShadowHeightInPix);
int shadowDrawableRes = a.getResourceId(R.styleable.StickyScrollView_stuckShadowDrawable,
-1);
if (shadowDrawableRes != -1) {
mShadowDrawable = context.getResources().getDrawable(shadowDrawableRes);
}
a.recycle();
}
/**
* Sets the height of the shadow drawable in pixels.
*
* @param height
*/
public void setShadowHeight(int height) {
mShadowHeight = height;
}
public void setup() {
stickyViews = new ArrayList<View>();
}
private int getLeftForViewRelativeOnlyChild(View v) {
int left = v.getLeft();
while (v.getParent() != getChildAt(0)) {
v = (View) v.getParent();
left += v.getLeft();
}
return left;
}
private int getTopForViewRelativeOnlyChild(View v) {
int top = v.getTop();
while (v.getParent() != getChildAt(0)) {
v = (View) v.getParent();
top += v.getTop();
}
return top;
}
private int getRightForViewRelativeOnlyChild(View v) {
int right = v.getRight();
while (v.getParent() != getChildAt(0)) {
v = (View) v.getParent();
right += v.getRight();
}
return right;
}
private int getBottomForViewRelativeOnlyChild(View v) {
int bottom = v.getBottom();
while (v.getParent() != getChildAt(0)) {
v = (View) v.getParent();
bottom += v.getBottom();
}
return bottom;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (!clipToPaddingHasBeenSet) {
clippingToPadding = true;
}
notifyHierarchyChanged();
}
@Override
public void setClipToPadding(boolean clipToPadding) {
super.setClipToPadding(clipToPadding);
clippingToPadding = clipToPadding;
clipToPaddingHasBeenSet = true;
}
@Override
public void addView(View child) {
super.addView(child);
findStickyViews(child);
}
@Override
public void addView(View child, int index) {
super.addView(child, index);
findStickyViews(child);
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
super.addView(child, index, params);
findStickyViews(child);
}
@Override
public void addView(View child, int width, int height) {
super.addView(child, width, height);
findStickyViews(child);
}
@Override
public void addView(View child, ViewGroup.LayoutParams params) {
super.addView(child, params);
findStickyViews(child);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (currentlyStickingView != null) {
canvas.save();
canvas.translate(getPaddingLeft() + stickyViewLeftOffset, getScrollY() +
stickyViewTopOffset
+ (clippingToPadding ? getPaddingTop() : 0));
canvas.clipRect(0, (clippingToPadding ? -stickyViewTopOffset : 0), getWidth() -
stickyViewLeftOffset,
currentlyStickingView.getHeight() + mShadowHeight + 1);
if (mShadowDrawable != null) {
int left = 0;
int right = currentlyStickingView.getWidth();
int top = currentlyStickingView.getHeight();
int bottom = currentlyStickingView.getHeight() + mShadowHeight;
mShadowDrawable.setBounds(left, top, right, bottom);
mShadowDrawable.draw(canvas);
}
canvas.clipRect(0, (clippingToPadding ? -stickyViewTopOffset : 0), getWidth(),
currentlyStickingView.getHeight());
if (getStringTagForView(currentlyStickingView).contains(FLAG_HASTRANSPARANCY)) {
showView(currentlyStickingView);
currentlyStickingView.draw(canvas);
hideView(currentlyStickingView);
} else {
currentlyStickingView.draw(canvas);
}
canvas.restore();
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
redirectTouchesToStickyView = true;
}
if (redirectTouchesToStickyView) {
redirectTouchesToStickyView = currentlyStickingView != null;
if (redirectTouchesToStickyView) {
redirectTouchesToStickyView = ev.getY() <= (currentlyStickingView.getHeight() +
stickyViewTopOffset)
&& ev.getX() >= getLeftForViewRelativeOnlyChild(currentlyStickingView)
&& ev.getX() <= getRightForViewRelativeOnlyChild(currentlyStickingView);
}
} else if (currentlyStickingView == null) {
redirectTouchesToStickyView = false;
}
if (redirectTouchesToStickyView) {
ev.offsetLocation(0, -1
* ((getScrollY() + stickyViewTopOffset) - getTopForViewRelativeOnlyChild
(currentlyStickingView)));
// XKJ add TODO: remove this
currentlyStickingView.invalidate();
}
return super.dispatchTouchEvent(ev);
}
private boolean hasNotDoneActionDown = true;
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (redirectTouchesToStickyView) {
ev.offsetLocation(0,
((getScrollY() + stickyViewTopOffset) - getTopForViewRelativeOnlyChild
(currentlyStickingView)));
}
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
hasNotDoneActionDown = false;
}
if (hasNotDoneActionDown) {
MotionEvent down = MotionEvent.obtain(ev);
down.setAction(MotionEvent.ACTION_DOWN);
super.onTouchEvent(down);
hasNotDoneActionDown = false;
}
if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent
.ACTION_CANCEL) {
hasNotDoneActionDown = true;
}
return super.onTouchEvent(ev);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
doTheStickyThing();
if (mOnScrollHandler != null) {
mOnScrollHandler.onScrollChanged(l, t, oldl, oldt);
}
int maxScroll = getChildAt(0).getHeight() - getHeight();
if (getChildCount() > 0 && t == maxScroll) {
if (mOnScrollToEnd != null) {
mOnScrollToEnd.onScrollToEnd();
}
}
if (getChildCount() <= 0 && t == getChildAt(0).getHeight()) {
if (mOnScrollToTop != null) {
mOnScrollToTop.onScroollToTop();
}
}
}
public void setOnScrollListener(OnScrollChangedListener handler) {
mOnScrollHandler = handler;
}
public interface OnScrollChangedListener {
public void onScrollChanged(int l, int t, int oldl, int oldt);
}
public interface IOnScrollToEnd {
public void onScrollToEnd();
}
public interface IOnScroollToTop {
public void onScroollToTop();
}
public void setOnScrollToEndListener(IOnScrollToEnd handler) {
mOnScrollToEnd = handler;
}
private void doTheStickyThing() {
View viewThatShouldStick = null;
View approachingView = null;
for (View v : stickyViews) {
int viewTop = getTopForViewRelativeOnlyChild(v) - getScrollY() + (clippingToPadding ?
0 : getPaddingTop())
- MIN_STICK_TOP;// add 50dp
if (viewTop <= 0) {
if (viewThatShouldStick == null
|| viewTop > (getTopForViewRelativeOnlyChild(viewThatShouldStick) -
getScrollY() + (clippingToPadding ? 0
: getPaddingTop()))) {
viewThatShouldStick = v;
}
} else {
if (approachingView == null
|| viewTop < (getTopForViewRelativeOnlyChild(approachingView) -
getScrollY() + (clippingToPadding ? 0
: getPaddingTop()))) {
approachingView = v;
}
}
}
if (viewThatShouldStick != null) {
stickyViewTopOffset = approachingView == null ? MIN_STICK_TOP : Math.min(MIN_STICK_TOP,
getTopForViewRelativeOnlyChild(approachingView) - getScrollY()
+ (clippingToPadding ? 0 : getPaddingTop()) - viewThatShouldStick
.getHeight());
if (viewThatShouldStick != currentlyStickingView) {
if (currentlyStickingView != null) {
stopStickingCurrentlyStickingView();
}
// only compute the left offset when we start sticking.
stickyViewLeftOffset = getLeftForViewRelativeOnlyChild(viewThatShouldStick);
startStickingView(viewThatShouldStick);
}
} else if (currentlyStickingView != null) {
stopStickingCurrentlyStickingView();
}
}
private void startStickingView(View viewThatShouldStick) {
currentlyStickingView = viewThatShouldStick;
if (getStringTagForView(currentlyStickingView).contains(FLAG_HASTRANSPARANCY)) {
hideView(currentlyStickingView);
}
if (((String) currentlyStickingView.getTag()).contains(FLAG_NONCONSTANT)) {
post(invalidateRunnable);
}
}
private void stopStickingCurrentlyStickingView() {
if (getStringTagForView(currentlyStickingView).contains(FLAG_HASTRANSPARANCY)) {
showView(currentlyStickingView);
}
currentlyStickingView = null;
removeCallbacks(invalidateRunnable);
}
/**
* Notify that the sticky attribute has been added or removed from one or
* more views in the View hierarchy
*/
public void notifyStickyAttributeChanged() {
notifyHierarchyChanged();
}
private void notifyHierarchyChanged() {
if (currentlyStickingView != null) {
stopStickingCurrentlyStickingView();
}
stickyViews.clear();
findStickyViews(getChildAt(0));
doTheStickyThing();
invalidate();
}
private void findStickyViews(View v) {
if (v instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) v;
for (int i = 0; i < vg.getChildCount(); i++) {
String tag = getStringTagForView(vg.getChildAt(i));
if (tag != null && tag.contains(STICKY_TAG)) {
stickyViews.add(vg.getChildAt(i));
} else if (vg.getChildAt(i) instanceof ViewGroup) {
findStickyViews(vg.getChildAt(i));
}
}
} else {
String tag = (String) v.getTag();
if (tag != null && tag.contains(STICKY_TAG)) {
stickyViews.add(v);
}
}
}
private String getStringTagForView(View v) {
Object tagObject = v.getTag();
return String.valueOf(tagObject);
}
private void hideView(View v) {
if (Build.VERSION.SDK_INT >= 11) {
v.setAlpha(0);
} else {
AlphaAnimation anim = new AlphaAnimation(1, 0);
anim.setDuration(0);
anim.setFillAfter(true);
v.startAnimation(anim);
}
}
private void showView(View v) {
if (Build.VERSION.SDK_INT >= 11) {
v.setAlpha(1);
} else {
AlphaAnimation anim = new AlphaAnimation(0, 1);
anim.setDuration(0);
anim.setFillAfter(true);
v.startAnimation(anim);
}
}
/**
* 解决vviewpager在scrollview滑动冲突的问题
*/
// 滑动距离及坐标
private float xDistance, yDistance, xLast, yLast;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
xLast = ev.getX();
yLast = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
xDistance += Math.abs(curX - xLast);
yDistance += Math.abs(curY - yLast);
// com.ihaveu.utils.Log.i("test", "curx:"+curX+",cury:"+curY+",xlast:"+xLast+",
// ylast:"+yLast);
// xLast = curX;
// yLast = curY;
if (xDistance > yDistance) {
return false;
}
}
return super.onInterceptTouchEvent(ev);
}
}
七、 TabLayoutFragment类
package com.example.yangdechengapplication.scrollview;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.example.yangdechengapplication.R;
/**
* Created by decheng.yang on 2017/10/26.
*/
public class TabLayoutFragment extends android.support.v4.app.Fragment {
private TextView tv_content;
private View view;
private CustomViewPager customViewPager;
private String content = "";
private int position = 0;
public void setCustomViewPager(CustomViewPager customViewPager) {
this.customViewPager = customViewPager;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (getArguments() != null) {
content = (String) getArguments().get("content");
position = (int) getArguments().get("position");
}
view = inflater.inflate(R.layout.fragment_tablayoutfragment, container, false);
customViewPager.setObjectForPosition(view, position);
super.onCreateView(inflater, container, savedInstanceState);
tv_content = (TextView) view.findViewById(R.id.tv_content);
tv_content.setText(content);
return view;
}
}
八、 TabLayoutFragment的布局xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textColor="#DA3850" />
</LinearLayout>
如果对你有帮助,赏我1元奶粉钱吧,多谢!
微信:
支付宝: