叠加会消耗所有触摸事件

时间:2014-08-29 10:02:40

标签: java android android-layout

我的应用会在屏幕的左边缘放置一个不可见的叠加层,如果用户从下半部分滑动,我想抓住此事件并对其执行某些操作。问题是,不仅仅是下半部分,边缘上半部分(宽度为8dp)的所有触摸事件也被消耗掉,因此不会传递给它下面的应用程序。

布局文件:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:custom="http://schemas.android.com/apk/res-auto"
              android:orientation="horizontal"
              android:layout_width="wrap_content"
              android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/llLauncher"
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:background="@color/transparentblack80"
        android:visibility="gone">

        <be.robinj.ubuntu.unity.launcher.AppLauncher
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            custom:icon="@drawable/launcher_bfb"
            custom:special="true"
            android:onClick="lalBfb_clicked"
            android:id="@+id/lalBfb"
            android:layout_marginTop="2dp"
            android:tag="partOfLauncher" />

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/scrLauncherAppsContainer"
            android:scrollbars="none"
            android:layout_weight="1"
            android:fillViewport="false"
            android:tag="partOfLauncher">

            <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/llLauncherPinnedApps"
                android:layout_gravity="top"
                android:tag="partOfLauncher">
            </LinearLayout>
        </ScrollView>

    </LinearLayout>

    <LinearLayout
        android:id="@+id/llListenerContainer"
        android:orientation="vertical"
        android:layout_width="8dp"
        android:layout_height="match_parent"
        android:weightSum="2"
        android:gravity="bottom">

        <LinearLayout
            android:id="@+id/llListener"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#FF0000">
        </LinearLayout>

    </LinearLayout>

    <LinearLayout
        android:id="@+id/llShadow"
        android:orientation="vertical"
        android:layout_width="160dp"
        android:layout_height="match_parent"
        android:background="@drawable/launcherservice_shadow"
        android:visibility="gone"
        android:tag="shadow">
    </LinearLayout>
</LinearLayout>

llListenerContainer及其子元素llListener在这里具有重要意义。默认情况下隐藏其他两个元素,并在检测到屏幕左下角的下半部分时显示。

在下面的屏幕截图中,我通过给它一个红色背景颜色llListener可见;

Screenshot with llListener made visible

所以红色区域内的触摸应该由我的服务处理,但触摸左边缘的上半部分应该只是由它下面的应用程序处理。

相关的Java代码;

public class LauncherService extends Service
{
    private WindowManager wm;
    private TouchListener touchListener;
    private LinearLayout layout;
    private LinearLayout llListenerContainer;
    private LinearLayout llListener;
    private LinearLayout llLauncher;
    private LinearLayout llShadow;

    @Override
    public IBinder onBind (Intent intent)
    { return null; }

    @Override
    public void onCreate ()
    {
        super.onCreate ();

        this.wm = (WindowManager) this.getSystemService (WINDOW_SERVICE);

        LayoutInflater inflater = (LayoutInflater) this.getSystemService (Service.LAYOUT_INFLATER_SERVICE);
        this.layout = (LinearLayout) inflater.inflate (R.layout.service_launcher, null, false);

        this.llLauncher = (LinearLayout) this.layout.findViewById (R.id.llLauncher);
        this.llListenerContainer = (LinearLayout) this.layout.findViewById (R.id.llListenerContainer);
        this.llListener = (LinearLayout) this.layout.findViewById (R.id.llListener);
        this.llShadow = (LinearLayout) this.layout.findViewById (R.id.llShadow);

        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);

        params.gravity = Gravity.TOP | Gravity.LEFT;
        params.x = 0;
        params.y = 0;

        this.touchListener = new TouchListener (this);

        lalBfb.setOnTouchListener (this.touchListener);
        this.llListener.setOnTouchListener (this.touchListener);
        this.llShadow.setOnTouchListener (this.touchListener);

        this.wm.addView (this.layout, params);
    }

    @Override
    public int onStartCommand (Intent intent, int flags, int id)
    {
        this.layout.setVisibility (intent.getBooleanExtra ("show", true) ? View.VISIBLE : View.GONE);
        return super.onStartCommand (intent, flags, id);
    }

    @Override
    public void onDestroy ()
    {
        super.onDestroy ();

        this.wm.removeView (this.layout);
    }

    //# Event handlers #//
    public void swipeRight ()
    {
        this.llLauncher.setVisibility (View.VISIBLE);
        this.llShadow.setVisibility (View.VISIBLE);
        this.llListenerContainer.setVisibility (View.GONE);
    }

    public void swipeLeft ()
    {
        this.llLauncher.setVisibility (View.GONE);
        this.llShadow.setVisibility (View.GONE);
        this.llListenerContainer.setVisibility (View.VISIBLE);
    }
}

public class TouchListener implements View.OnTouchListener
{
    private LauncherService parent;

    public TouchListener (LauncherService parent)
    { this.parent = parent; }

    @Override
    public boolean onTouch (View view, MotionEvent event)
    {
        int id = view.getId ();

        if (id == R.id.llListener)
        {
            this.parent.swipeRight ();

            return true;
        }
        else if (id == R.id.llShadow)
        {
            this.parent.swipeLeft ();

            return true;
        }

        return false;
    }
}

1 个答案:

答案 0 :(得分:0)

我还没有机会在设备上尝试此操作,但可能是因为您正在将父布局的高度定义为&#34; match_parent&#34;。

您可以尝试将其更改为&#34; wrap_content&#34; ?