Search code examples
androiduser-interfaceandroid-layoutandroid-scrollview

Detect click on screen when in landscape


I'm having some trouble with detecting screen clicks on the GUI. Works in portrait but fails in landscape, see below.

I have a GUI (Fragment) which contains some instructions + images. The user is required to tap anywhere on the screen to proceed. In order capture the click/tap event, I have put in a View(topview) that fill the entire screen and sits onto of other elements, I then listen for clicks on this view and it works fine.

The problem is when in landscape mode, the text and images take up to much room. So the whole thing is now wrapped in a ScrollView. This is where the problem begins. When the ScrollView is active, (i.e. you can scroll/scroll bars are visible), my view on top (topview) disappears. It seems that when in landscape mode the height of content in a ScrollView is being changed. As an experiment I replaced the View with a Button and the Button goes from filling the screen in portrait to being normal height in landscape mode when the ScrollView is usable.

Is there a way of me detecting the user tapping on the screen, which works with the ScrollView control as the top element. I've tried rearranging the GUI in several ways but without success, and I've tried adding onClick event handlers to the ScrollView, also without success.

My Layout is below, note my top view is semi-transparent red, so I could see the area it covered.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:clickable="true" >

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/txtInstructions"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal|center_vertical"
            android:padding="10dp"
            android:text="@string/instructions"
            android:textColor="@color/blue"
            android:textSize="20sp" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:adjustViewBounds="true"
            android:maxWidth="250dp"
            android:padding="20dp"
            android:src="@drawable/main_camera" />
    </LinearLayout>


    <View
        android:id="@+id/view_to_listen_for_touch"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#88FF0000"
        android:clickable="true" />

</RelativeLayout>


Solution

  • One thing that works(although looks like more like a hack(pretty ugly)) is to programatically add the special View in code(in the onCreate method) and set its dimensions based on the parent RelativeLayout's exact dimensions. Here is a snippet of code:

    //...
            final RelativeLayout parent = (RelativeLayout) findViewById(R.id.ff);
            final View layer = new View(this);
            layer.setBackgroundColor(Color.parseColor("#88FF0000"));
            // the ScrollView really doesn't like this View ,using this without the
            // runnable will not work
            layer.setLayoutParams(new RelativeLayout.LayoutParams(
                    RelativeLayout.LayoutParams.MATCH_PARENT,
                    RelativeLayout.LayoutParams.MATCH_PARENT));
            layer.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    Toast.makeText(getApplicationContext(), "SDFD",
                            Toast.LENGTH_SHORT).show();
                }
            });
            parent.addView(layer);
            // this is required because if we use directly the getWidth/getHeight we
            // will get 0/0
            layer.post(new Runnable() {
    
                @Override
                public void run() {
                    layer.setLayoutParams(new RelativeLayout.LayoutParams(parent
                            .getWidth(), parent.getHeight()));
                }
            });
    //...