无法将 ViewPager 放入 ScrollVIew/NestedScrollView
Unable to Put ViewPager inside a ScrollVIew/NestedScrollView
我有一个 ViewPager,它位于父线性布局中,在 ViewPager 下方有一些按钮。 ViewPager 一直运行良好,直到最近我将父级从 LinearLayout 更改为 ScrollView。现在 ViewPager 消失了。请不要将其标记为垃圾邮件或重复。
此外,Playstore 上目前有大量应用程序正在使用它。查看此应用 - link
我尝试了什么:
- setFillViewport (true) - 这对我不起作用。
- 将 layout_height 设置为 0dp
- 使用 CustomScrollView
所有这些都对我没有帮助。我是 运行 Android M.
上的应用
这是我的 layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
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:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".activities.HomeActivity">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:onClick="pagerClick"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="top"
android:layout_weight="1"
android:overScrollMode="never"/>
<RelativeLayout
android:layout_weight="0.8"
android:layout_marginTop="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
.....two buttons
</RelativeLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
问题:
我怎样才能做到这一点?另外,有官方的方法吗?
最好使用 recyclerView 并在适配器中添加 Viewpager 作为其 child。您需要拦截 recyclerview 的触摸以将滚动交给 ViewPager。
public class TouchInterceptRecyclerView extends RecyclerView {
private boolean interceptTouch = true;
private static final int MIN_DISTANCE = 200;
private float downX = 0, downY = 0, moveX = 0, moveY = 0, upX = 0, upY;
public TouchInterceptRecyclerView(Context context) {
super(context);
}
public TouchInterceptRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (getRvTop() == 0) {
onTouchEvent(ev);
}
return interceptTouch;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
moveX = event.getX();
moveY = event.getY();
break;
case MotionEvent.ACTION_UP:
upX = event.getX();
upY = event.getY();
break;
}
float deltaX = upX - downX;
if (getViewTop() == 0 && moveY > downY && Math.abs(moveY - downY) > MIN_DISTANCE) { // moving down
interceptTouch = true;
}else if (Math.abs(deltaX) > MIN_DISTANCE) {
if (upX > downX) { // Left to Right swipe action
interceptTouch = false;
}else { // Right to left swipe action
interceptTouch = false;
}
} else { // screen tap
interceptTouch = false;
}
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
}
@Override
public void onScrolled(int dx, int dy) {
if (getViewTop() <= 0) {
interceptTouch = false; // dispatch the touch to child when reached top
} else {
interceptTouch = true; // do not dispatch the touch event
}
super.onScrolled(dx, dy);
}
public int getViewTop() {
int top = 0;
View v = this.getChildAt(1);
if (v == null) {
v = this.getChildAt(0);
}
if (v != null && v instanceof LinearLayout) {
top = v.getTop();
}
return top;
}
public int getRvTop() {
int top = -1;
View v = this.getChildAt(1);
if (v == null) {
v = this.getChildAt(0);
}
if (v != null && v instanceof LinearLayout) {
ViewPager vp = (ViewPager) v.findViewById(R.id.single_pager);
if (vp != null) {
int currentPos = vp.getCurrentItem();
RecyclerView rv = (RecyclerView) vp.findViewWithTag("recyclerview" + currentPos);
if (rv != null) {
View v1 = rv.getChildAt(0);
if (v1 != null && v1 instanceof CardView) {
top = v1.getTop() - ResourceUtils.getDimensionPixelOffset(R.dimen.padding_20); // deducting 20 as we have give top margin as 20 to the top layout
}
}
}
}
return top;
}
}
在 RecyclerView 的适配器中,您可以像这样添加 ViewPager :
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
View view;
switch (viewType) {
case TYPE_VIEW_PAGER:
view = LayoutInflater.from(context).inflate(R.layout.pager, parent, false);
viewHolder = new ViewPagerAdapter(context, view);
break;
}
return viewHolder;
}
我通过固定 ViewPager 的高度解决了这个问题,例如:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
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:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".activities.HomeActivity">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:onClick="pagerClick"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="top"/>
...
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
我有一个 ViewPager,它位于父线性布局中,在 ViewPager 下方有一些按钮。 ViewPager 一直运行良好,直到最近我将父级从 LinearLayout 更改为 ScrollView。现在 ViewPager 消失了。请不要将其标记为垃圾邮件或重复。
此外,Playstore 上目前有大量应用程序正在使用它。查看此应用 - link
我尝试了什么:
- setFillViewport (true) - 这对我不起作用。
- 将 layout_height 设置为 0dp
- 使用 CustomScrollView
所有这些都对我没有帮助。我是 运行 Android M.
上的应用这是我的 layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
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:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".activities.HomeActivity">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:onClick="pagerClick"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="top"
android:layout_weight="1"
android:overScrollMode="never"/>
<RelativeLayout
android:layout_weight="0.8"
android:layout_marginTop="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
.....two buttons
</RelativeLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
问题:
我怎样才能做到这一点?另外,有官方的方法吗?
最好使用 recyclerView 并在适配器中添加 Viewpager 作为其 child。您需要拦截 recyclerview 的触摸以将滚动交给 ViewPager。
public class TouchInterceptRecyclerView extends RecyclerView {
private boolean interceptTouch = true;
private static final int MIN_DISTANCE = 200;
private float downX = 0, downY = 0, moveX = 0, moveY = 0, upX = 0, upY;
public TouchInterceptRecyclerView(Context context) {
super(context);
}
public TouchInterceptRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (getRvTop() == 0) {
onTouchEvent(ev);
}
return interceptTouch;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
moveX = event.getX();
moveY = event.getY();
break;
case MotionEvent.ACTION_UP:
upX = event.getX();
upY = event.getY();
break;
}
float deltaX = upX - downX;
if (getViewTop() == 0 && moveY > downY && Math.abs(moveY - downY) > MIN_DISTANCE) { // moving down
interceptTouch = true;
}else if (Math.abs(deltaX) > MIN_DISTANCE) {
if (upX > downX) { // Left to Right swipe action
interceptTouch = false;
}else { // Right to left swipe action
interceptTouch = false;
}
} else { // screen tap
interceptTouch = false;
}
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
}
@Override
public void onScrolled(int dx, int dy) {
if (getViewTop() <= 0) {
interceptTouch = false; // dispatch the touch to child when reached top
} else {
interceptTouch = true; // do not dispatch the touch event
}
super.onScrolled(dx, dy);
}
public int getViewTop() {
int top = 0;
View v = this.getChildAt(1);
if (v == null) {
v = this.getChildAt(0);
}
if (v != null && v instanceof LinearLayout) {
top = v.getTop();
}
return top;
}
public int getRvTop() {
int top = -1;
View v = this.getChildAt(1);
if (v == null) {
v = this.getChildAt(0);
}
if (v != null && v instanceof LinearLayout) {
ViewPager vp = (ViewPager) v.findViewById(R.id.single_pager);
if (vp != null) {
int currentPos = vp.getCurrentItem();
RecyclerView rv = (RecyclerView) vp.findViewWithTag("recyclerview" + currentPos);
if (rv != null) {
View v1 = rv.getChildAt(0);
if (v1 != null && v1 instanceof CardView) {
top = v1.getTop() - ResourceUtils.getDimensionPixelOffset(R.dimen.padding_20); // deducting 20 as we have give top margin as 20 to the top layout
}
}
}
}
return top;
}
}
在 RecyclerView 的适配器中,您可以像这样添加 ViewPager :
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
View view;
switch (viewType) {
case TYPE_VIEW_PAGER:
view = LayoutInflater.from(context).inflate(R.layout.pager, parent, false);
viewHolder = new ViewPagerAdapter(context, view);
break;
}
return viewHolder;
}
我通过固定 ViewPager 的高度解决了这个问题,例如:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
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:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".activities.HomeActivity">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:onClick="pagerClick"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="top"/>
...
</LinearLayout>
</android.support.v4.widget.NestedScrollView>