How to handle multitouch events in Android with multiple nested layouts? - android

I am designing an Android application and I would like to find a way to handle multitouch between multiple nested views.
My layout is as following:
Relative layout
|
|---Linear layout
| \---Linear layout
| \--Button A
|
|---Linear layout
\---Button B
The two buttons take approximately 50% of the screen size. I would like to be able to press the two buttons at the same time one after the other. I can press button B and then A but when I press A, I'm not able to press B.
It seems that it's a normal behaviour if we consider the way that Android handles event. I googled my problem and I only found complex solutions that involve rewriting a custom view and the "DispatchTouchEvent" method.
Do you know if there's a easy way to avoid that behaviour (being able to press A then B and B and then A)?
I wrote a minimal example: run an activity with the following layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:splitMotionEvents="true"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="epl.groupe16.testbutton.MainActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:text="New Button"
android:id="#+id/button" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:weightSum="2">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="New Button"
android:id="#+id/button21"
/>
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="New Button"
android:id="#+id/button20"
android:layout_weight="1"
android:visibility="invisible" />
</LinearLayout>
I can press the lowest button, hold my touch and then click on the upper button but if I try the highest first, the lowest isn't clickable.
Thank you in advance

Finally we found that there's no easy solution for this.
But there was some workarounds that I would like to share if somebody had the same problem.
First, there's a manual way to do that: reconding a proper way to propagate event by creating custom views and overwriting the method "DispatchTouchEvent". It's quite long but it can solve the problem.
Also, Google added a PercentRelativeLayout in API 23, so you can place all of your components in a single view. But, we were targetting API 19 and Android Marshmallow doesn't represent a huge percentage of the current devices.
Finally, we decided to code our custom SurfaceView and touchEvent listener. We drawed our components in a SurfaceView and handled clics manually.
I hope it will help you :)

Related

Android Layout xml "buttons stacking" (newbie )

I just started with android development. I just need a screen with some buttons on it that can contact a webserver, to trigger an action there, but i have not even gotten that far.
When i add buttons to the layout, even if they are nicely sided by side, they end up ontop of each other, with the button created last ontop.
And furtermore i have changed the color, but it does not seem to be moved end up in the simulator.
This is a fresh design (2nd try) and i dont understand what is going on. I dont really know what files to include :)
I realize this is something simple, but im just overwhelmed
thank you
Lasse
Phone and design view
You're probably using a FrameLayout, which just stacks things on top of each other and only supports gravity.
For your use case, you can use a LinearLayout, a RelativeLayout or a ConstraintLayout. Here's an example using LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="Select releases since last candy fix" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="96dp"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:text="Button 1" />
<Button
android:layout_width="96dp"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:text="Button 2" />
</LinearLayout>
</LinearLayout>
Have a look at the different layouts to see which one better fits your needs, ConstraintLayout would allow you to flatten your layout, which is good for performance.

How can I create a multiline, multicolumn list item layout?

I am creating a messaging app and am currently working on the inbox. I'm using a RecyclerView to display the list of conversations and would like each list item to look like this:
Leftmost is the contact image at 90dp x 90dp
The first row has two columns--the contact name and the date. The date should not be a fixed size as I currently have it, but fit at most DD/MM/YYYY (can be smaller in the case of something like "Sunday") and should be anchored to the right margin. The contact(s) should expand as necessary to fill any space up to the date.
The second row contains as much text of the last message as will fit.
I was going to use layout_weight but that doesn't work in a RelativeLayout (and doesn't allow the contact names to elongate in the case of a shorter date) and LinearLayout doesn't let me use layout_toEndOf. I'm a newbie at Android development so I'm not sure if one of those is the "right" answer.
What's the proper way of accomplishing the layout I'm looking for?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/conversation_info"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/activity_horizontal_margin">
<RelativeLayout
android:id="#+id/conversation_image_layout"
android:layout_width="90dp"
android:layout_height="90dp">
<ImageView
android:id="#+id/conversation_contact_image"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
<TextView
android:id="#+id/conversation_contact_name"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:gravity="center_vertical"
android:textSize="#dimen/conversations_contact_font_size"
android:layout_toEndOf="#id/conversation_image_layout" />
<TextView
android:id="#+id/conversation_date"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_toEndOf="#id/conversation_contact_name"
android:gravity="right"
android:paddingRight="#dimen/activity_horizontal_margin"
android:textSize="#dimen/conversations_date_font_size" />
<TextView
android:id="#+id/conversation_snippet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/conversation_contact_name"
android:textSize="#dimen/conversations_snippet_font_size"
android:layout_toRightOf="#id/conversation_image_layout" />
</RelativeLayout>
</LinearLayout>
This is what a list item currently looks like (I haven't loaded contact images yet). It's fine for the most part (though my layout code is probably incredibly bloated so I'd appreciate if anyone could point out ways to make it more concise) but notice how the date isn't on the same level as the contact name and wraps:
One of the textView in question has the MarginTop attribute, and the other one doesn't. Either remove it on both or add it to both:
<TextView
android:id="#+id/conversation_contact_name"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:gravity="center_vertical"
android:textSize="#dimen/conversations_contact_font_size"
android:layout_toEndOf="#id/conversation_image_layout" />
<TextView
android:id="#+id/conversation_date"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_toEndOf="#id/conversation_contact_name"
android:gravity="right"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:textSize="#dimen/conversations_date_font_size" />
Also, I'd recommend that you use Linear Layouts with nested Linear Layouts and weights, for better performance on different screens and devices. This may all fall apart if you run it on a different device. Don't trust me, try it :)
After it became clear to me that some of the layout parameters didn't mean what I thought they did, I spent some more time looking at my choices.
It is not recommended to nest LinearLayouts/use layout_weight within a list item, as the number of views created increases rapidly as more items are added. I managed to minify my code and keep it in a single RelativeLayout with the following code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/conversation_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/activity_horizontal_margin">
<ImageView
android:id="#+id/conversation_contact_image"
android:layout_width="64dp"
android:layout_height="64dp"/>
<TextView
android:id="#+id/conversation_contact_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/conversations_contact_font_size"
android:layout_toEndOf="#id/conversation_contact_image"/>
<TextView
android:id="#+id/conversation_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignBaseline="#id/conversation_contact_name"
android:textSize="#dimen/conversations_date_font_size"/>
<TextView
android:id="#+id/conversation_snippet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/conversation_contact_name"
android:textSize="#dimen/conversations_snippet_font_size"
android:layout_toEndOf="#id/conversation_contact_image"/>
</RelativeLayout>
Notable changes:
No nested tags - It was unnecessary to group the first line in its own layout
Used layout_alignBaseline - #Vucko pointed out that I was using marginTop on the contact name but not the date. Even after removing it, the two were still misaligned. android:gravity had no effect and it turns out none of these actually affect the text inside the layout
Used layout_alignParentEnd to fix the date issue. I've realized that in my case, a layout component usually only needs to reference one other in order to properly align itself relative to the rest of the layout.

Placing Button to Overlapping Two Layouts with Layout Weight with Kitkat and below support

I am trying to place a button overlapping two layouts. The Layouts must have the layout_weight as shown in the image below, I've been struggling on it for a while, .. I succeeded with the below code .. but only for api 22 (lollipop) & 23 (MarshMallow).. Problem occurs in API 19 (Kitkat) & below .. The Lower layout seem to cover the button .. ie, button is half visible from the top.
Please help me to achieve like in image with all android version support ..
TIA !
Code which worked on API 22 & 23 but not in 19 and Below:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.automovill.automovill.testing">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="1">
<LinearLayout
android:id="#+id/LL1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight=".55"
android:background="#2961a7"
android:orientation="vertical">
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="-25dp"
android:background="#ffd016"
android:padding="10dp"
android:text="TESTING"
android:textColor="#000"
android:textStyle="bold" />
<RelativeLayout
android:id="#+id/LL2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="-25dp"
android:layout_weight=".45"
android:background="#163d6d">
</RelativeLayout>
</LinearLayout>
To be honest, I think you'll have to perform all kinds of crazy gymnastics to get the standard layouts do this. LinearLayout is not the right tool because the expectation is that the elements are all adjacent to each other (you may have been exploiting a bug before).
You can do standard layout gymnastics, or you can go ahead a write your own ViewGroup to manage the layout positions of the child view to conform to your needs. You'll end up having to compute pixels and all that. Probably no way to avoid these manual computations since the usual layout typically expect view adjacency rather than overlap.
Maybe try it with adding the following code to your button's layout:
android:layout_marginBottom="-25dp"
I would try to move the button at the top of the layout file. There is an implicit rule in RelativeLayout about the z ordering of the views. The further down the view the higher is the z value.

Pass keyboard event to gridview?

I have a custom layout for the google tv and to get the layout to work, I override the dispatchkeyEvent in my activity to get my layout to work with the dpad. My layout also uses the gridview, and since I override the dispatchKeyEvent, I cant use the dpad with the gridview. Is there anyway to pass the key event to the gridview so I can use it?
Edit1: Apparently, the gridview cannot be focusd according to .isFocusable(). Is there anyway to force it to become focusable?
Edit2: I think the problem is the VideoView that is taking focus from all the controls?
Heres the layout I'm using. If I take out the VideoView, i am able to use the controls. The UI and Workspace layouts is my UI overlay over the video. Is there anway to get around this?
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_weight="1" >
<VideoView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<RelativeLayout
android:id="#+id/ui"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom" >
<LinearLayout
android:id="#+id/workspace"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom" >
</LinearLayout>
</RelativeLayout>
</FrameLayout>

Android screen "watermarked"

How could be done such thing, like "watermark" on top of any other Activities on Android?
In detail: I need to show some message on top of everything what is running on my device. No matter if this is game, movie, app.
Is possible to achive something on Android? My phone is rooted.
Is possible to use some OpenGL features?
Use this code.
At first, I am using here FrameLayout, that is transparent and you can see "watermarked" text on image.
At second, I am using android:background="#99 000000" on my button and you also can see it on the image. First 2 digits, as i know, named alpha channel and you can set them from 0 to ff; 0 is fully transparent, and ff is non-transparent, as usual.
I think you get the idea or may be you can draw your custom image on canvas, put on your framelayout and set 50% trasparent-background. And you have to do this 50% transparent layers onto all your layouts and so, all activities will have watermark.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/frameLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<FrameLayout
android:id="#+id/frameLayout2"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:src="#drawable/ic_launcher" />
</FrameLayout>
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:background="#99000000" />
</LinearLayout>
</FrameLayout>
Use a master activity which have layout according to you. And then use this master activity in other activity by extending to child activity.
Its simple.
Yes, it is possible to run a base activity and over that some intended activity to perform the action you want.
Now, you can use the concept of sub-activities and activities in android to ensure this type of result.

Categories

Resources