我的Android ViewPager设置为在边界之外绘制视图(剪辑边界设置为false)。我在页面上显示的所有视图上都有一个触摸事件监听器。自定义视图显示在页面1上,在其剪切边界之外绘制并溢出到页面2.页面1上的触摸事件正常工作。滚动到第二页时,将显示剩余视图。问题是单击第2页时,自定义视图上的触摸事件(在页面1上添加)不会被调用。
PageViewActivity.cs
ViewPager mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setClipChildren(false);
mViewPager.setClipToPadding(false);
PageViewFragment.cs
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.page_layout, container, false);
setHasOptionsMenu(true);
View view1=(View)v.findViewById(R.id.view1);
view1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getActivity(), "View clicked",Toast.LENGTH_SHORT).show();
}
});return v;
}
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false" >
<View
android:id="@+id/view1"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginLeft="250dp"
android:layout_marginTop="20dp"
android:background="#ff0000" />
片段布局 - page_layout.xml
有什么建议吗?
答案 0 :(得分:0)
这里有一个问题。我们只能刷中间视图。这是因为触摸事件发生在ViewPagers边界之外。我们可以覆盖ViewPagerContainer的onTouchEvent并将事件分派给ViewPager来解决这个问题。
private ViewPager mPager;
@Override
protected void onFinishInflate() {
mPager = (ViewPager) getChildAt(0);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return mPager.dispatchTouchEvent(ev);
}
但事实是,你最好使用更现代的解决方案。
<android.support.design.widget.CoordinatorLayout 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:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.TabLayout
android:id="@+id/result_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/grey"
app:tabIndicatorColor="@color/colorPrimary"
app:tabMode="scrollable"
app:tabSelectedTextColor="@color/colorPrimary"
app:tabTextColor="@color/medium_grey" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
标签布局和正确设置的viewpager。虽然谷歌在他们的架构组件中完成导航位后,即使这样也会过时了。
答案 1 :(得分:0)
您必须手动检测触摸事件,并查看其坐标是否位于边界外的页面范围内。因此,在将触摸事件发送到寻呼机之前,要了解Tatarize所说的内容,您应该检查事件是否在视图寻呼机的其中一个页面中。
这是示例代码,我只检查x是否位于边界内而不是childContains()中的y。
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
return pager.dispatchTouchEvent(event);
case MotionEvent.ACTION_UP:
int childCount = pager.getChildCount();
int x = (int) event.getX();
int y = (int) event.getY();
for (int i = 0; i < childCount; i++) {
final View child = pager.getChildAt(i);
if (childContains(child, x)) {
// delay the click minimally in-case
// callOnClick performs mods on the pager
//
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
child.callOnClick();
}
}, 100);
return true;
}
}
break;
}
return pager.dispatchTouchEvent(event);
}
int[] loc = new int[2];
private boolean childContains(View child, final int x) {
child.getLocationOnScreen(loc);
int x1_child = loc[0];
int x2_child = x1_child + child.getWidth();
int x0 = x;
boolean isInside = x0 >= x1_child && x0 < x2_child;
Log.v("childContains()", String.format("x: %s x1_child: %s x2_child: %s isInside: %s",
x0, x1_child, x2_child, String.valueOf(isInside)));
return isInside;
}