compile 'com.android.support:design:22.2.1'
<?xml version="1.0" encoding="utf-8"?>
<com.example.administrator.jingdong.myview.PageContainer
android:id="@+id/container"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.example.administrator.jingdong.myview.Page
android:id="@+id/pageOne"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.stx.xhb.xbanner.XBanner
android:id="@+id/xbnr"
app:AutoPlayTime="1000"
android:layout_width="match_parent"
android:layout_height="500px"></com.stx.xhb.xbanner.XBanner>
<TextView
android:textSize="50px"
android:text="你猜"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/feilei_xiangqing_fragment_title"/>
<TextView
android:textSize="50px"
android:layout_marginTop="30px"
android:text="85"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:id="@+id/feilei_xiangqing_fragment_price"/>
</LinearLayout>
</com.example.administrator.jingdong.myview.Page>
<com.example.administrator.jingdong.myview.Page
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/pageBehavior">
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/web"></WebView>
</com.example.administrator.jingdong.myview.Page>
</com.example.administrator.jingdong.myview.PageContainer>
public class Page extends NestedScrollView {
private boolean scrollAble = true;
private float y;
private float oldy = 0;
private OnScrollListener onScrollListener;
public Page(Context context) {
this(context, null);
}
public Page(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public Page(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
ViewConfiguration.getTouchSlop();
}
public void setScrollAble(boolean scrollAble) {
this.scrollAble = scrollAble;
}
public void setScrollAble(boolean scrollAble, float y) {
this.scrollAble = scrollAble;
this.y = y;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (scrollAble) {
return super.onTouchEvent(ev);
} else {
switch (ev.getAction()) {
case MotionEvent.ACTION_MOVE:
float distanceY = 0;
float newY = 0;
if (oldy == 0) {
distanceY = 1;
newY = ev.getRawY();
} else {
newY = ev.getRawY();
distanceY = newY - oldy;
}
oldy = newY;
if (onScrollListener != null) {
onScrollListener.onScroll(distanceY, y);
}
return true;
case MotionEvent.ACTION_UP:
if (onScrollListener != null) {
onScrollListener.onScroll(-10000, y);
}
scrollAble = true;
oldy = 0;
return true;
default:
return true;
}
}
}
public void setScrollListener(OnScrollListener onScrollListener) {
this.onScrollListener = onScrollListener;
}
public interface OnScrollListener {
void onScroll(float scrollY, float y);
}
}
public class PageContainer extends CoordinatorLayout implements Page.OnScrollListener {
private Page child;
private PageBehavior behavior;
public PageContainer(Context context) {
this(context, null);
}
public PageContainer(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PageContainer(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setOnPageChanged(
PageBehavior.OnPageChanged onPageChanged) {
if (behavior != null) {
behavior.setOnPageChanged(onPageChanged);
}
}
@Override
public void onScroll(float scrollY, float distance) {
if (scrollY == -10000) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
scrollTo(0, 0);
}
}, -10);
} else {
int y = (int) (getScrollY() - scrollY);
if (y < distance) {
return;
}
scrollTo(0, y);
if (behavior != null) {
behavior.setScrollY((int) (distance - y));
}
}
}
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
if (child instanceof Page) {
this.child = ((Page) child);
this.child.setScrollListener(this);
}
LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
if (layoutParams.getBehavior() != null && layoutParams.getBehavior() instanceof PageBehavior) {
behavior = (PageBehavior) layoutParams.getBehavior();
}
}
public void backToTop(){
if (behavior!=null){
behavior.backToTop();
}
}
public void scrollToBottom(){
if (behavior!=null){
behavior.scrollToBottom();
}
}
}
public class PageBehavior extends CoordinatorLayout.Behavior {
private static final int PAGE_ONE = 1;
private static final int PAGE_TWO = 2;
private WeakReference<View> dependentView,childView;
private Scroller scroller;
private Handler handler;
private int status = PAGE_ONE;//记录状态
private float gap;
private int totalOne = 0;
private int scrollY = 0;
private int mode = 0;
public OnPageChanged mOnPageChanged;
public void setOnPageChanged(
OnPageChanged onPageChanged) {
mOnPageChanged = onPageChanged;
}
public PageBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
scroller = new Scroller(context);
handler = new Handler();
gap = 100;
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
//设定依赖视图为id是R.id.pageOne的View
if (dependency.getId() == R.id.pageOne) {
dependentView = new WeakReference<>(dependency);
childView=new WeakReference<>(child);
return true;
}
return false;
}
@Override
public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {
//child的布局
child.layout(0, 0, parent.getWidth(), child.getMeasuredHeight());
return true;
}
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
//让child随着依赖视图的属性变动而变动
child.setTranslationY(dependency.getMeasuredHeight() + dependency.getTranslationY());
return true;
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
//只监测Vertical方向的动作
scroller.abortAnimation();//停止动画
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
}
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
if (status == PAGE_ONE) {
if (dyUnconsumed > 0) {
View dependentView = getDependentView();
totalOne = (totalOne - dyUnconsumed);
dependentView.setTranslationY(totalOne * 0.5f);
}
if (dependentView.get().getTranslationY() < 0 && dyConsumed < 0) {
mode = 1;
((Page) dependentView.get()).setScrollAble(false, dependentView.get().getTranslationY());
}
} else if (status == PAGE_TWO) {
if (dyUnconsumed < 0) {
View dependentView = getDependentView();
totalOne = (totalOne + dyUnconsumed);
int newTranslate = (int) (-dependentView.getMeasuredHeight() - (totalOne * 0.5));
dependentView.setTranslationY(newTranslate);
}
if (dependentView.get().getTranslationY() > -dependentView.get().getHeight() && dyConsumed > 0) {
mode = 1;
((Page) child).setScrollAble(false, dependentView.get().getTranslationY());
}
}
}
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) {
super.onStopNestedScroll(coordinatorLayout, child, target);
totalOne = 0;
View dependentView = getDependentView();
float translationY = dependentView.getTranslationY();
if (status == PAGE_ONE) {
if (mode == 0) {
if (translationY < -gap) {
scroller.startScroll(0, (int) translationY, 0, (int) (-dependentView.getMeasuredHeight() - translationY));
status = PAGE_TWO;
if (mOnPageChanged!=null){
mOnPageChanged.toBottom();
}
} else {
scroller.startScroll(0, (int) translationY, 0, (int) (-translationY));
}
} else {
mode = 0;
if (scrollY < -gap) {
scroller.startScroll(0, scrollY, 0, -dependentView.getMeasuredHeight() - scrollY);
status = PAGE_TWO;
if (mOnPageChanged!=null){
mOnPageChanged.toBottom();
}
} else {
scroller.startScroll(0, scrollY, 0, -scrollY);
}
}
} else if (status == PAGE_TWO) {
if (mode == 0) {
if (translationY < -dependentView.getMeasuredHeight() + gap) {
scroller.startScroll(0, (int) translationY, 0, (int) (-dependentView.getMeasuredHeight() - translationY));
} else {
scroller.startScroll(0, (int) translationY, 0, (int) (-translationY));
status = PAGE_ONE;
if (mOnPageChanged!=null){
mOnPageChanged.toTop();
}
}
} else {
mode = 0;
if (scrollY < -dependentView.getMeasuredHeight() + gap) {
scroller.startScroll(0, scrollY, 0, -dependentView.getMeasuredHeight() - scrollY);
} else {
scroller.startScroll(0, scrollY, 0, -scrollY);
status = PAGE_ONE;
if (mOnPageChanged!=null){
mOnPageChanged.toTop();
}
}
}
}
handler.post(new Running());
}
private View getDependentView() {
return dependentView.get();
}
private class Running implements Runnable {
@Override
public void run() {
if (scroller.computeScrollOffset()) {
View dependentView = getDependentView();
dependentView.setTranslationY(scroller.getCurrY());
handler.post(this);
} else {
}
}
}
public void setScrollY(int scrollY) {
this.scrollY = scrollY;
}
public void backToTop(){
View dependentView = getDependentView();
float translationY = dependentView.getTranslationY();
if (status == PAGE_TWO) {
if (mode == 0) {
childView.get().setScrollY(0);
dependentView.setScrollY(0);
scroller.startScroll(0, (int) translationY, 0, (int) (-translationY));
status = PAGE_ONE;
if (mOnPageChanged!=null){
mOnPageChanged.toTop();
}
}
}
handler.post(new Running());
}
public void scrollToBottom(){
View dependentView = getDependentView();
float translationY = dependentView.getTranslationY();
dependentView.setScrollY(dependentView.getMeasuredHeight());
if (status == PAGE_ONE) {
if (mode == 0) {
scroller.startScroll(0, (int) translationY, 0, (int) (-dependentView.getMeasuredHeight() - translationY));
status = PAGE_TWO;
if (mOnPageChanged!=null){
mOnPageChanged.toBottom();
}
}
}
handler.post(new Running());
}
public interface OnPageChanged{
void toTop();
void toBottom();
}
}
R.id.pageOne 为ids ids为values下的xml文件
ids代码如下
<?xml version="1.0" encoding="utf-8"?>
<resources >
<item name="pageOne" type="id" />
</resources >
strings代码如下
// app:layout_behavior="@string/pageBehavior">为values下的string文件
com.example.administrator.jingdong.myview 为PageBehavior的包名
<resources>
<string name="app_name">webxiangqing</string>
<string name="pageBehavior" translatable="false" >
com.example.administrator.jingdong.myview.PageBehavior</string >
</
resources>
public class MainActivity extends AppCompatActivity {
private PageContainer container;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView web = findViewById(R.id.web);
web.loadUrl("https://github.com/ysnows");
container = (PageContainer) findViewById(R.id.container);
container.setOnPageChanged(new PageBehavior.OnPageChanged(){
@Override
public void toTop() {
//位于第一页
Toast.makeText(MainActivity.this, "我是第一页", Toast.LENGTH_SHORT).show();
}
@Override
public void toBottom() {
Toast.makeText(MainActivity.this, "你好啊", Toast.LENGTH_SHORT).show();
}
});
}