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);
}
}
}
Related
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.
i'm actually really new at coding in java and on AndroidStudio and i'm trying to update an application that already exist.
I have 3 LinearLayout that look like 3 square inside each other and inside the last one, i have a TewtView.
the first one is the main one and is always visible.
When i put my two last LinearLayout in visibility="GONE" my LinearLayout disapear, and i want that my textView will be always visible, even if the LinearLayout that contains it are invisible.
It is possible?
<LinearLayout
style="#style/ColPlayer"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<LinearLayout
style="#style/SquareBogey"
android:visibility="gone"
android:layout_width="70dp"
android:layout_height="50dp"
android:orientation="horizontal"
android:id="#+id/outersquare">
<LinearLayout
style="#style/SquareBogey"
android:visibility="gone"
android:layout_width="60dp"
android:layout_height="40dp"
android:orientation="horizontal"
android:id="#+id/innersquare">
<TextView
android:id="#+id/PlayerCJ01"
style="#style/ColCJPlayer"
android:layout_height="wrap_content"
android:ems="1" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
Just ask me if you need more informations.
Thanks
When setting the visibility of a parent layout to GONE or INVISIBLE, all its children will also become GONE or INVISIBLE.
If you want to show the TextView but not its parent LinearLayout, than you could either move the TextView out of the LinearLayout, or you could remove the styling of the LinearLayout so it will look like its gone, but obviously it's still there.
Setting the visibility of the LinearLayout to GONE and its child TextView's visibility to VISIBLE won't work and therefore is not an option.
Instead of setting the visibility as GONE for the LinearLayouts, maybe you can set their background/border as transparent by changing their style.
It depends on your use case, if it suits your need.
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 making an app, and I have the following XML file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#f4f4f4" >
<ExpandableListView
android:id="#+id/lvExp"
android:layout_width="match_parent"
android:layout_height="325dp" />
<Button
android:id="#+id/add_claim"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Claim" />
</LinearLayout>
I made a button called View_list that wants to see only the expandable list view on the entire page. what I did is create a new XML file, and added the follwing include statement:
<include android:id="#+id/lvExp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
However, I realized that this will now work for two reasons
1 - There is no layout ID
2- I only want the list, not the button and everything else I am going to put in the original layout. What is going to happen is if I add something to the list, I need to be able to view it without the option of adding antthing to it.
My question is therefore this:
How do I find the layout ID and how can I prevent the entire layout from showing, and only show the list. I would really appreciate some advice.
The include should say:
<include layout="#layout/View_list"
android:id="#+id/lvExp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
This includes the View_list.xml layout in another layout.
But I dont really understand why you would use an include here if you don't want to re-use the whole layout, but only the list part of it. includes exist to easily use layouts in other layouts, if you need just a ListView, use just a ListView.
EDIT: I'm not sure anymore if I got your question right, but I'll not delete the answer because you commented on it.
If you want to hide the button or other Views on the click of a button, you can set their visibility to gone programmatically.
I have met a very strange issue in android FrameLayout.
I am trying a very simple game which has a SurfaceView, and when the game ends, I want to popup another view on top probably displaying some text. This is very similar to android sample lunarlander code. However I can't get it work. Here is the strange issue:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/game_frame"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.tmh.FunMatch.MainGamePanel
android:id="#+id/game_panel"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.tmh.FunMatch.MyText
android:id="#+id/text"
android:text="test"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:textColor="#88ffffff"
android:textSize="24sp"/>
</RelativeLayout>
For above FrameLayout, I want to show the second TextView when game finished. However it won't show after I call TextView.setVisibility(VISIBLE).
I did a lot experiment, if I initially set the TextView as VISIBLE, then at some point set it to INVISIBLE in the code. (My understanding is the TextView must be initially showed on the screen once then I turned it into INVISIBLE). If I did so, when the game finished, the TextView will be correctly shown.
I highly doubt it's an android bug. I changed android LunarLander code, I don't know why LunarLander did work and show the Text on the screen.
If anyone had run into the same issue, please tell me what's wrong with my code or is there a hidden bug?
Thanks