I have a layout with some clickable views in it.
I have implemented swipe gesture as per this.
This is working great if you swipe in an empty area, but it does not work if you start swiping inside one of the views inside the layout.
How can this be avoided? Adding onSwipeListener to ever single view in the activity seems insane. Is there a better way?
my working solution to this problem is using an invisible layer above the view with children as following:
<RelativeLayout
android:id="#+id/contentLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/linearLayout"
android:layout_alignStart="#+id/linearLayout"
android:layout_alignParentTop="true">
...
</RelativeLayout>
<View
android:id="#+id/gesture_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/linearLayout"
android:layout_alignStart="#+id/linearLayout"
android:layout_alignParentTop="true"
android:focusable="true"
android:focusableInTouchMode="true" />
where contentLayout contains multiple children including some buttons.
Second step is catching touch events on this gesture_view and proxying them to both contentLayout and my GestureDetector code (similar to the one you linked on the question) as following:
gesture_view.setOnTouchListener { _, event ->
contentLayout.dispatchTouchEvent(event)
gestureListener.onTouch(event)
true
}
Note, you need to be careful about how you deliver the events to the view behind gesture_view. Simply contentLayout#onTouch will not work. It has to be contentLayout.dispatchTouchEvent
Set android:clickable=false in your child views. This will prevent them from intercepting the touch events from the parent.
Related
Guess it could also be asked as making an AlertDialog behave completely like a modal dialog.
I want to be able to display the AlertDialog and immediately stop everything on screen except the dialog buttons to stop reacting to any user action, so the button cannot be clicked, the checkbox cannot be checked and so on.
I know I could do this by, when the dialog is displayed, setting rest of element as not enabled, and when closing the dialog, setting them as enabled, but problem is dialogs may show or not depending on several factors, and there are a lot of elements to control which makes this way prone to error.
Maybe there's a more simple way in which the dialog is defined with some flag and by default fulfills that behavior.
I've already set the dialog with the modal flag this way, but it only helps in no closing the dialog if user taps outside of it without touching any other UI element (except for free space on layout), it still allows behaviour from other UI elements, like this:
dialog3.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
Is there any way to do what I'm saying?
I am not quite sure if this is the proper answer to your question. However, I can think of a workaround here.
I would like to suggest you keep a layout that overlaps the existing UI elements and hence stops the touching of those elements. Please take the following layout as an example.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<android.support.design.widget.TextInputLayout
android:id="#+id/input_mobile_number_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp">
<EditText
android:id="#+id/input_mobile_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Mobile number"
android:inputType="phone"
android:maxLength="11"
android:textSize="30sp"
android:textStyle="bold" />
</android.support.design.widget.TextInputLayout>
<android.support.v7.widget.AppCompatButton
android:id="#+id/btn1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/input_mobile_number_layout"
android:layout_marginBottom="24dp"
android:layout_marginTop="24dp"
android:padding="12dp"
android:text="SUBMIT" />
<RelativeLayout
android:id="#+id/overlap"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#80000000"
android:visibility="gone" />
</RelativeLayout>
Please check the RelativeLayout with id overlap.
So when you will be showing the AlertDialog, you need to make change the visibility of the overlap layout to VISIBLE and preventing other UI elements to be clicked. Then again, when you are dismissing the dialog, you need to make the overlap layout to GONE.
Please note that the overlap layout has a transparent background color to make this not very unusual. Also the default visibility is set to GONE.
Hope that helps!
Call this from the activity
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
To undo:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
Alternative solution:
Pass the root layout as the view
private static void setViewAndChildrenEnabled(View view, boolean enabled) {
view.setEnabled(enabled);
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
setViewAndChildrenEnabled(child, enabled);
}
}
}
This thing is driving me crazy. Here's how it works
1. everything is set as default
ripple effect works
list view item separator is visible
2. white background added to the widget layout
ripple lost
list view item separator also gone
looks like list item style has been removed
Here's the code
main widget layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:background="#android:color/white" -- this line only applies for case 2
android:padding="#dimen/widget_padding">
<TextView
...
android:background="#color/primary"
android:textColor="#android:color/white"/>
<ListView
...
android:drawSelectorOnTop="true""/>
<TextView
...
android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout>
list item layout
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
...
android:id="#+id/widgetItem">
<TextView
...
android:textColor="#android:color/black"
android:textSize="14sp"/>
<TextView
...
android:textColor="#color/negative_amount"
android:textSize="16sp"
android:textStyle="bold"/>
</RelativeLayout>
I've spent a day trying all possible combinations but nothing helped. And I don't get the fact that unrelated background change to some layout around the list view completely alters the behaviour. WTF?
I would like to solve it in the cleanest way possible - e.i. no hacking with custom selectors. This should work straight out of the box if possible.
It looks like you're using a dark theme for your activity, so the ripple is white and thus not visible over a white background. The simplest solution is to use a light variant of the theme, which will cause the ripple to be black.
For example, if you're using an AppCompat theme, you can add this line to your ListView:
<ListView
...
android:drawSelectorOnTop="true"
style="#style/Theme.AppCompat.Light"/>
You can also apply this to a view hierarchy, e.g.:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:background="#android:color/white"
android:padding="#dimen/widget_padding"
android:theme="#style/Theme.AppCompat.Light">
This will cause the theme to be used in the LinearLayout and all of its child views.
Also, you can specify a theme activity-wide or even app-wide by adding android:theme attribute to the <activity> or <application> tag to your AndroidManifest.xml.
I've built a View which displays data driven by the respective Java Activity class. The data comes from the first element of a Collection.
On a button click from the view (onClick), I want to display the second element of the Collection in the view (replacing the first element).
What is the best way to achieve this? Here is what I was thinking:
onClick invokes a method in the Activity class which modifies the state of existing view elements?
onClick reloads the Activity and the state of the Collection still exists to be able to present?
Some other way?
Not sure if 1 will work as the Model isn't bound to the view elements? Some kind of refresh will be needed.
2 sounds overkill if you just want to keep the view structure the same but modify the state of elements.
Thanks in advance.
Use ViewSwitcher
<ViewSwitcher
android:id="#+id/viewswitcher"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<View
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="firstClick" />
<View
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher" />
android:onClick="secondClick"
</ViewSwitcher>
In java code
firstClick()
{
viewswitcher.setDisplayedChild(1);
}
secondClick()
{
//whatever you need
}
Here when you click on a the first view(It can be a button), the second view can be made visible by replacing the first one. Use it as per your convenience.
I was over thinking this. All I had to do was update the state of the view objects in the java layer and the view would automatically 'paint' the changes.
In my app, users can either take a picture or record a video. The file is then saved and its path is passed through an intent to the next activity, which displays it for editing.
My question is, how can I easily use the same view for either a video or an image?
I tried dynamically adding a view at runtime when I know what the file type is, but it turned out to be too hard to configure, not to mention the issues that VideoViews have with being rotated.
Edit:
I forgot to mention that using the same view would be preferable, since I'm not actually going to do anything to the contents that's specific to each kind of view.
Add both the ImageView and VideoView in your layout. Then set the visibility to GONE or VISIBLE for the one you want.
You can create two child views, one for the image and one for the video. And depending on the type of your view you can hide/show your child views.
You can also use FrameLayout for this
By using frame layout / Relative layout you can place a view on top of another view. After creating the views like i mention and using the visibility Gone & Visible you can manage to handle it..
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/ImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/my_drawable"
android:scaleType="fitCenter"
android:visibility="gone"/>
<VideoView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:padding="5dp"
android:id="#+id/VideoView"
android:visibility="gone"/>
</FrameLayout>
Then based on your usage you can control it dynamically like below
// register the views
ImageView mImageView= (ImageView)findViewById(R.id.ImageView);
VideoView mVideoView= (VideoView)findViewById(R.id.VideoView);
// check your conditions like show video view r image view here
if(VideoView)
{
mVideoView.setVisibility(View.VISIBLE);
mImageView.setVisibility(View.GONE);
}
else if(ImageView)
{
mImageView.setVisibility(View.VISIBLE);
mVideoView.setVisibility(View.GONE);
}
Hope it will work for you :)
I am adding accessebility support to some application. It works fine with standart UI elements (buttons for example), but for some reason does not work with my custom element, wich is RelativeLayout with ImageView and TextView (it looks like icon). I've defined android:focusable="true" and set contentDescription.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:contentDescription=”my content description”
android:focusable="true">
<ImageView
...
/>
<TextView
...
/>
</RelativeLayout>
Could someone please list here all posible causes?
UPDATE:
Is there some way to know what layouts are on the screen at the moment and what order do they have (some layouts are transparent)?
Use hierarchy viewer for understanding where is your invisible views.
The android docs have a section about designing for accessibility, is this any use to you?