In my main page of my application, server sends me some flags. One of then is advertise flag. if it is set to true i need to show advertise and if it is set to false i shouldn't show it.
now, the problem. I need to put the space of advertise in XML file like this.
<?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">
<RileativeLayout
android:id="#+id/adv"
android:layout_width="fill_parent"
android:layout_height="100dip">
</RileativeLayout>
.
.
.
</LinearLayout >
according to above code if the flag is set to false, i don't show advertise but the gap is still remain in my screen. How to remove it from my code dynamically and shift other views (which are blow of it) up?
as mentioned above in the comments for your question: a view has a few different View options.
View.VISIBLE: this means that it's visible and can be seen by the user.
View.INVISIBLE: this means the view is still in the layout but cannot be seen by the user (the user can't interact with it either).
View.GONE: this means the view is destroyed and is no longer part of it.
to remove a View completely from the layout you should use View.GONE, if you're going to make it visible you should use View,INVISIBLE.
try this when your flag is false
add.setVisibility(View.GONE);
You can "remove" the View by changing the visibility of it. Use
View ad = findViewById(R.id.adv);
ad.setVisibility(View.GONE);
Related
In my Android app I have a layout for an activity that presents a choice.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/wrapper"
android:orientation="vertical">
<include layout="#layout/choices" />
<include layout="#layout/choice_one" />
<include layout="#layout/choice_two" />
</LinearLayout>
In layout/choices the user sees two buttons. One button shows layout/choice_one and the other shows layout/choice_two. (The parent in layout/choice_one and layout/choice_two is initially set to android:visibility=gone.)
So when a user chooses either choice_one or choice_two, essentially I'm setting the visibility to VISIBLE. That works great.
The issue is that inside of both choice_one and choice_two I have shared elements with the same ID. For example I have a TextView with ID header. (I did this because I figured only one of those layouts would be visible and they use the same things.)
The issue is that I use Butterknife, and it seems like if I Bind header, when I set the visibility on choice_one or choice_two, I have a 50/50 chance of correctly calling header.setText("Blah") on the appropriate header element.
I'm sure I can get around this by giving unique IDs to all elements in the layouts or ditching Butterknife and using findViewById instead. But is there another way I can target a shared ID inside of a layout without ditching Butterknife or my shared layouts?
I figured this out. (Writing it out helped, so I'll keep it here in case someone else stumbles upon it.) Instead of using include in xml and inflating layouts there, I just subclassed ViewGroup for my two layouts and added them to wrapper:
ChoiceOne choiceOne = new ChoiceOne();
wrapper.addView(choiceOne);
My question is simple: How to disable any event on a View in Android? (including removing its focussability, like I just want it to be there visually but be inexistant on everything else)
And does it work on a whole view tree? (like if I disable events on the root, all the events will be disabled for its children?).
Now, before you say anything I have tried all the following:
setEnabled
setFocusable
setSelected
setClickable
setActivated
And none of these methods appear to work, seriously.
I have tried them directly on a WebView, as well as on the parent layout on everything but I am still able to interact with it.
Any idea?
Thanks!
EDIT#1
The solution that consists in adding a view on top of the view that needs to be disabled doesn't work. Actually, it's still possible to click on the inner view, I have tried with a simple example:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#ff0000">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Click Me!"
/>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00000000"
/>
</FrameLayout>
Here it's still possible to click on the button.
EDIT#2
The reason why I want to do this is related to the following question that I asked weeks ago.
What I have is a ListViewacting as a navigation bar which is underneath a View that holds the content of my app. The problem with this implementation is that when I try to scroll through the ListView when there is a focusable view in the layer on top of it, well the ListView doesn't scroll and instead it's the top view that takes focus (That's the case when there is a
Webview or an EditText etc.).
So yes as mentioned in one of the answers, I can disable any click events on a WebView by overriding setOnTouchListener but the view remains focussed and I think this is the reason why I am still having the same issue with my navigation bar.
Simply put a view on top of your view. You can toggle it on off by setting view.visibility = gone/visible.
<FrameLayout>
<WebView/>
<FrameLayout This view will be on top/>
</FrameLayout>
Edit: Just stumpled upon this link: https://stackoverflow.com/a/3856199/969325
Basically disables all touch event for the webview. Tryed that?
Edit 2 reedit: Try to set the visibility to gone for the the top view below your listview.
As I am actually not very confident with programatically changing Views, I have following problem:
At the first start of my app, I want to have an overlay for the main screen, that tells the user to have a look at the settings, as there are two critical options the user has to configure.
I don't want to use an AlertDialog and rather not use a wizard. So, I decided to take an approach similar to Go SMS and create an overlay at the first start. The mockup I created looks like this:
Normal menu:
First start:
So these are the problems I have:
Like I said, I don't want to use a screenshot overlaying on first start, as this would take too much space and would not be language and screen independent.
I would have the circle as an png, but I don't know how exactly put it over the image
The same problem with the text
And finally I want to put a semi-transparent white over the app. It does not necessarily need the hole for the icon, though it would be nice.
In case you need the Layout Source, you can get it at pastebin
So, I just need to get a start here, if it is better to use LayoutInflater or ViewStub and how to realize it, as I have absolutely no experience with it...
Thanks!
/edit: I uploaded a new, more well-arranged layout.
I have faced a similar problem, I client wanted a walkthrough of the application, where the entire screen had to become whiter (as they said: "transparent"), except for the button being explained by an overlay speech-bubble.
Fortunately for you, your layout is not nearly as complicated as the one I had to work with :)
Now, you can get the transparency-effect in two ways, either have a white background and call all the views setAlpha() methods, or you can create a half-transparent white overlay.
If you go with the overlay, you'll have to find a way to display the opaque buttons through the overlay. This can get a bit complicated.
If you go with the first option, you can just setAlpha(1) on the opaque view to get it to show up.
The setAlpha() method is only available from api version 11+, so if you target an earlier version, you might have to do it in a slightly more complicated way.
Example of setting alpha on views pre-honeycomb:
Layout for your buttons (make them however you want, just make them similar so you can loop through them):
<LinearLayout
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:tag="image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/tile"/>
<TextView
android:tag="text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF000000"
android:text="button1"/>
</LinearLayout>
In your program, when you are want to make the buttons transparent:
LinearLayout l = (LinearLayout) findViewById(R.id.button1);
((ImageView)l.findViewWithTag("image")).setAlpha(0x7F);
((TextView)l.findViewWithTag("text")).setTextColor(0x7F000000);
When you have decided on how you want to create the transparency effect, you will have to decide on how to display the overlay-text/bubble. You'll most likely want to put this in a separate layer on top of your entire layout, to make sure that it is not affected by your new view.
One way to achieve this is by changing your root layout element to a FrameLayout, and then creating/displaying in this. e.g:
<FrameLayout background="#FFFF"> <!-- white background, just in case -->
<LinearLayout>
<!-- the rest of your layout -->
</LinearLayout>
<LinearLayout visibility="gone"> <!-- this will be your overlay view -->
<ImageView /> <!-- the arrow/ring -->
<TextView /> <!-- the description -->
</LinearLayout>
</FrameLayout>
When the introduction is displayed, you set the position of the hidden overlay-view to the position of the table item to be explained, change the text to an appropriate string/resource and display the view.
When the introduction is over, you reset the alpha values of all buttons, and set the visibility of the overlay to gone again.
Since I don't have much experience with ViewStub, I would do it with LayoutInflater.
First of all, you need to have a second layout loaded on top of your current layout. The easiest is to have a FrameLayout, which has as one child your current view, and the dynamically you load the second child on the first start. When you load a content view in an Activity, it will be attached to some already created views (some DecorView, a FrameLayout, etc). So you can either re-use the existing FrameLayout, or you can create a new one.
I would vote for the second solution, since it's more stable (I just mentioned the other possibility in case you want to minimize the number of layers).
So, as a first step, wrap your current layout inside a FrameLayout, and give it an id, let's say "#id/root".
Then, in the onCreate method, you can have something like this:
setContentView(R.layout.main);
if (isFirstRun()) {
ViewGroup parent = (ViewGroup)findViewById(R.id.root); // locate the FrameLayout
LayoutInflater li = LayoutInflater.from(this); // get an instance of LayoutInflater
li.inflate(R.layout.overlay, parent);
}
So far you will have the overlay loaded. Now it's up to you to define the overlay.
To make the whitening effect, just set the following attribute on the root view in your overlay.xml layout:
android:background="#40ffffff"
To position the circle, first you need to find it's location. You can use the View.getLocationOnScreen to get the absolute coordinate of the icon (below the circle) on the screen. Then you can have two options:
either create a custom view (for the overlay) and manually draw the circle at the given location
or add the circle using an ImageView and adjust the left and top margins based on the coordinates
I have activity and a lot of widgets on it, some of them have animations and because of the animations some of the widgets are moving (translating) one over another. For example the text view is moving over some buttons . . .
Now the thing is I want the buttons to be always on the front. And when the textview is moving I want to move behind the buttons.
I can not achieve this I tried everything I know, and "bringToFront()" definitelly doesn't work.
note I do not want to control the z-order by the order of placing element to layout cause I simply can't :), the layout is complex and I can not place all the buttons at the begging of the layout
You can call bringToFront() on the view you want to get in the front
This is an example:
yourView.bringToFront();
With this code in xml
android:translationZ="90dp"
I've been looking through stack overflow to find a good answer and when i couldn't find one i went looking through the docs.
no one seems to have stumbled on this simple answer yet:
ViewCompat.setTranslationZ(view, translationZ);
default translation z is 0.0
An even simpler solution is to edit the XML of the activity. Use
android:translationZ=""
bringToFront() is the right way, but, NOTE that you must call bringToFront() and invalidate() method on highest-level view (under your root view), for e.g.:
Your view's hierarchy is:
-RelativeLayout
|--LinearLayout1
|------Button1
|------Button2
|------Button3
|--ImageView
|--LinearLayout2
|------Button4
|------Button5
|------Button6
So, when you animate back your buttons (1->6), your buttons will under (below) the ImageView. To bring it over (above) the ImageView you must call bringToFront() and invalidate() method on your LinearLayouts. Then it will work :)
**NOTE: Remember to set android:clipChildren="false" for your root layout or animate-view's gradparent_layout. Let's take a look at my real code:
.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:hw="http://schemas.android.com/apk/res-auto"
android:id="#+id/layout_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/common_theme_color"
android:orientation="vertical" >
<com.binh.helloworld.customviews.HWActionBar
android:id="#+id/action_bar"
android:layout_width="match_parent"
android:layout_height="#dimen/dimen_actionbar_height"
android:layout_alignParentTop="true"
hw:titleText="#string/app_name" >
</com.binh.helloworld.customviews.HWActionBar>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/action_bar"
android:clipChildren="false" >
<LinearLayout
android:id="#+id/layout_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:gravity="center_horizontal"
android:orientation="horizontal" >
</LinearLayout>
<ImageView
android:id="#+id/imgv_main"
android:layout_width="#dimen/common_imgv_height"
android:layout_height="#dimen/common_imgv_height"
android:layout_centerInParent="true"
android:contentDescription="#string/app_name"
android:src="#drawable/ic_launcher" />
<LinearLayout
android:id="#+id/layout_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center_horizontal"
android:orientation="horizontal" >
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
Some code in .java
private LinearLayout layoutTop, layoutBottom;
...
layoutTop = (LinearLayout) rootView.findViewById(R.id.layout_top);
layoutBottom = (LinearLayout) rootView.findViewById(R.id.layout_bottom);
...
//when animate back
//dragedView is my layoutTop's child view (i added programmatically) (like buttons in above example)
dragedView.setVisibility(View.GONE);
layoutTop.bringToFront();
layoutTop.invalidate();
dragedView.startAnimation(animation); // TranslateAnimation
dragedView.setVisibility(View.VISIBLE);
GLuck!
Try FrameLayout, it gives you the possibility to put views one above another. You can create two LinearLayouts: one with the background views, and one with foreground views, and combine them using the FrameLayout. Hope this helps.
If you are using ConstraintLayout, just put the element after the other elements to make it on front than the others
i have faced the same problem.
the following solution have worked for me.
FrameLayout glFrame=(FrameLayout) findViewById(R.id.animatedView);
glFrame.addView(yourView);
glFrame.bringToFront();
glFrame.invalidate();
2nd solution is by using xml adding this attribute to the view xml
android:translationZ=""
You can try to use the bringChildToFront, you can check if this documentation is helpful in the Android Developers page.
There can be another way which saves the day. Just init a new Dialog with desired layout and just show it. I need it for showing a loadingView over a DialogFragment and this was the only way I succeed.
Dialog topDialog = new Dialog(this, android.R.style.Theme_Translucent_NoTitleBar);
topDialog.setContentView(R.layout.dialog_top);
topDialog.show();
bringToFront() might not work in some cases like mine. But content of dialog_top layout must override anything on the ui layer. But anyway, this is an ugly workaround.
You can use BindingAdapter like this:
#BindingAdapter("bringToFront")
public static void bringToFront(View view, Boolean flag) {
if (flag) {
view.bringToFront();
}
}
<ImageView
...
app:bringToFront="#{true}"/>
The order of the overlapping views really depends of 4 things:
The attribute android:elevation which is measured in dp/sp
The attribute android:translationZ which is also measured in dp/sp.
In Constraint Layout, the order in which you put the views in your Component Tree is also the order to be shown.
The programmatically order that you set through methods like view.bringToFront() in your kotlin/java code.
The numerals 1 and 2 compite with each other and take preference over the points 3 and 4: if you set elevation="4dp" for View 1 and translationZ="2dp" for View 2, View 1 will always be on top regardless of the numerals 3 and 4.
Thanks to Stack user over this explanation, I've got this working even on Android 4.1.1
((View)myView.getParent()).requestLayout();
myView.bringToFront();
On my dynamic use, for example, I did
public void onMyClick(View v)
{
((View)v.getParent()).requestLayout();
v.bringToFront();
}
And Bamm !
You can use elevation attribute if your minimum api level is 21. And you can reorder view to the bottom of other views to bring it to front. But if elevation of other views is higher, they will be on top of your view.
If you are using a LinearLayout you should call myView.bringToFront() and after you should call parentView.requestLayout() and parentView.invalidate() to force the parent to redraw with the new child order.
Arrange them in the order you wants to show. Suppose, you wanna show view 1 on top of view 2. Then write view 2 code then write view 1 code. If you cant does this ordering, then call bringToFront() to the root view of the layout you wants to bring in front.
Try to use app:srcCompat instead of android:src
You need to use framelayout. And the better way to do this is to make the view invisible when thay are not require. Also you need to set the position for each and every view,So that they will move according to there corresponding position
You can set visibility to false of other views.
view1.setVisibility(View.GONE);
view2.setVisibility(View.GONE);
...
or
view1.setVisibility(View.INVISIBLE);
view2.setVisibility(View.INVISIBLE);
...
and set
viewN.setVisibility(View.VISIBLE);
I recently updated my phone to gingerbread and to my horror one of my apps stopped working!
The app consists of a SurfaceView and a layout (view) that shows up as an overlay over this SurfaceView.
THe xml looks like this:
<?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"
>
<com.mycompany.MySurfaceView
android:id="#+id/myview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<include layout="#layout/settings"
android:layout_alignTop="#id/myview"
android:visibility="invisible"
android:id="#+id/settings"
/>
</RelativeLayout>
When the user press the menu button I use this code to show the view:
View settings = (View)findViewById(R.id.settings);
settings.setVisibility(View.VISIBLE);
This worked flawlessy on versions earlier than 2.3 but now the behaviour is very random.
Observations
Very rarely everything works.
Sometimes the view shows up after hiding / unhiding it.
Sometimes you can press the buttons on the view (even though it's invisible) this makes the view show up for the rest of the application lifetime.
The getVisibility method always report the correct value.
What I've tried
Rebuilding draw cache
Using BringToFront method
Post invalidate
Setting the initial value of the view to "visible", this makes everything work, but I really want it to be initially invisible!
If anyone wants to check the problem you can try it for yourself in my app (it's on market, search for "chainparticles").
Thanks!
Solved it by changing the views initial state to "gone". WTF?!