簡體   English   中英

android傳遞在視圖剪輯邊界之外繪制的子視圖的觸摸事件(ViewPager第1頁到第2頁)

[英]android Passing touch events of a Child view drawn outside of view clip bounds (ViewPager Page 1 to Page 2)

我的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

有什么建議么?

這里有一個問題。 我們只能刷中間視圖。 這是因為觸摸事件發生在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。 雖然谷歌在他們的架構組件中完成導航位后,即使這樣也會過時了。

您必須手動檢測觸摸事件,並查看它的坐標是否位於邊界外的頁面范圍內。 因此,在將觸摸事件發送到尋呼機之前,關閉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;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM