Okay, so I've done some looking around and I see how you are SUPPOSED to do it, but for me, it is just not working.
I need to be able to set the alpha of a RelativeLayout both in XML and in code. For my XML, I have the following
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/player_controls"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:alpha="0.0">
<RelativeLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/player_controls_touch_me"
>
</RelativeLayout>
</RelativeLayout>
I get the error: no resource identifier found for attribute 'alpha' in package 'android'
Also, based on the Android documentation, I should be able to call setAlpha(double) on any View object, but when I try to make that call on a RelativeLayout it tells me that this method is not defined for this object.
Why am I not able to control the alpha transparency for a RelativeLayout object in Android? Am i missing something? Thanks!
Update
Although using the visibility property works, it prevents me from be able to click on the ViewGroup. This is important for me because I am utilizing the OnTouchListener of the ViewGroup.
What I am trying to do is to have a layer with media controls, initially hidden. when the user taps anywere on the screen, I want the controls to fade in and when they tap the screen again I want the controls to fade out. I have this part already working. I am using a viewgroup that sits over-top my entire application with an OnTouchListener attached that can determine if it has or hasn't been touched. My problem is that after the animation runs to fade out the controls, they re-appear. If I use #Hydrangea suggestion, I can have it fade out and immediately made invisible. This gives me the desired effect, but then the ViewGroup is unclickable and the user cannot get the controls to come back (or go away, depending on what we decide to do first).
I hope this makes sense.
You'll want to use a alpha animation to fade things in and out. This will maintain your touch events for your layouts. Here's an example
public class Main extends Activity {
/** Called when the activity is first created. */
private boolean mShowing = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.textview).setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
if(mShowing){
Animation animation = new AlphaAnimation(1.0f, 0.0f);
animation.setFillAfter(true);
arg0.startAnimation(animation);
} else {
Animation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setFillAfter(true);
arg0.startAnimation(animation);
}
mShowing = !mShowing;
}
});
}
}
Here's the accompanying xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="#+id/textview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
android:clickable="true"
/>
</LinearLayout>
Unless you need levels of alpha between 0 and 1, I'd suggest, if you truly want to make this item invisible, to use setVisibility();
android:visibility="invisible"
I checked out the android:alpha line, and my ide doesn't find it either. I can't guess why, though... the documentation seems pretty clear.
The alpha property is new in Android 3.0, and it's not the most efficient way to hide a view. Use View.setVisibility() or android:visibility to achieve what you want.
You can set alpha by setting the (background) color i guess. Color values can be in the format of #aarrggbb (alpha, red, green, blue).
You can add to the right answer the following option:
animation.setDuration(xxx);
To each animation instance. In this way your animation will look better.
Based on your discription, you should be able to create a view that contains only the relative layout and have the onClickListener set to it. This way you can set the visibility of the relative layout to invisible, but still register a click.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/clickable_layout"
android:layout_height="match_parent"
android:layout_width="match_parent" >
<RelativeLayout
android:id="#+id/player_controls"
android:layout_height="match_parent"
android:layout_width="match_parent" >
<RelativeLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/player_controls_touch_me"
>
</RelativeLayout>
</RelativeLayout>
</FrameLayout>
Use onTouchEvent in Activity, and then you could get touch event to control to your RelativeLayout even if it is "invisible".
Related
In my Android app, I am needing to implement a scene transition that involves a change in the elevation (z-index) of one of the elements. As you can see in the image below in the start scene on the left the blue arc is displayed beneath the image of the dog. In the final transition displayed on the right, the image of the dog is displayed underneath the blue arc. My desire is to have a changeBounds transition of the image start first and then slightly later do a changeBounds transition of the arc. At about halfway through the transition, the bottom of the image should be positioned above the arc. At this halfway point I'd like the elevation/z-index of the image to change so that the dog image is displayed underneath the blue arc.
I currently have the theme of my app configured to use the following transitionSet for this scene change.
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
android:transitionOrdering="together"
android:duration="2000">
<changeBounds
android:startDelay="0"
android:duration="1000"
android:resizeClip="false"
>
<targets>
<target android:targetId="#id/charlie"/>
</targets>
</changeBounds>
<transition class="com.motb.transitiontest.ElevationTransition">
android:startDelay="0"
android:duration="1000"
<targets>
<target android:targetId="#id/charlie"/>
<target android:targetId="#id/arc1"/>
</targets>
</transition>
<changeBounds
android:startDelay="300"
android:duration="1000"
>
<targets>
<target android:targetId="#id/arc1"/>
<target android:targetId="#id/helloText" />
</targets>
</changeBounds>
</transitionSet>
I'm attempting to have the elevation change using this custom "ElevationTransition" shown below:
public class ElevationTransition extends Transition {
public static final String TAG = "ElevationTransition" ;
public ElevationTransition(Context context, AttributeSet attributes ) {
super( context, attributes );
}
private static final String PROPNAME_TRANS_Z = "com.motb:transition:transz";
#Override
public void captureStartValues(TransitionValues transitionValues) {
float translationZ = transitionValues.view.getTranslationZ() ;
transitionValues.values.put(PROPNAME_TRANS_Z + "_start" , translationZ );
}
#Override
public void captureEndValues(TransitionValues transitionValues) {
float translationZ = transitionValues.view.getTranslationZ() ;
transitionValues.values.put(PROPNAME_TRANS_Z + "_end", translationZ );
}
#Override
public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
if (startValues == null || endValues == null) {
return null;
}
final View view = endValues.view;
float startElevation = (Float) startValues.values.get(PROPNAME_TRANS_Z + "_start");
float endElevation = (Float) endValues.values.get(PROPNAME_TRANS_Z + "_end" );
if (startElevation != endElevation) {
view.setTranslationZ(startElevation);
return ObjectAnimator.ofFloat(view, View.TRANSLATION_Z,
startElevation, endElevation);
}
return null;
}
}
The main activity just displays the blank map using the following layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.motb.transitiontest.MainActivity"
android:id="#+id/main"
android:onClick="onClick"
android:background="#drawable/treasuremap"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="#+id/fragmentContainer"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
A click on the map replaces the above FrameLayout with a fragment displaying the bottom "card" that uses the following layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="250dp"
tools:context="com.motb.transitiontest.MainActivity"
android:id="#+id/main"
android:background="#android:color/transparent"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="#drawable/arc_bg"
android:backgroundTint="#ff0000ff"
android:layout_alignParentBottom="true"
android:transitionName="rv1"
android:id="#+id/arc1"
android:translationZ="20dp"
>
<TextView
android:id="#+id/helloText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World Transition Test"
android:layout_marginStart="165dp"
android:layout_marginTop="27dp"
android:textSize="40dp"
android:gravity="left"
android:transitionName="tv1"
android:textColor="#ffffffff"
/>
</RelativeLayout>
<ImageView
android:layout_width="300px"
android:layout_height="300px"
android:layout_alignParentTop="true"
android:layout_marginTop="80dp"
android:layout_marginStart="20dp"
android:transitionName="iv1"
android:src="#drawable/charlie"
android:id="#+id/charlie"
android:translationZ="30dp"
android:stateListAnimator="#null"
/>
</RelativeLayout>
A click on the fragment, starts the second activity with the larger image of the dog using the xml below:
`
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.motb.transitiontest.Activity2"
android:theme="#android:style/Theme.Translucent.NoTitleBar"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.motb.transitiontest.Activity2"
android:layout_marginTop="200dp"
android:background="#drawable/arc_bg"
android:layout_alignParentBottom="true"
android:transitionName="rv1"
android:id="#+id/arc1"
android:backgroundTint="#ff0000ff"
android:translationZ="40dp"
>
<TextView
android:id="#+id/helloText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:text="Hello World Transition Test"
android:textSize="40dp"
android:textAlignment="center"
android:transitionName="tv1"
android:textColor="#ffffffff"
/>
</RelativeLayout>
<ImageView
android:id="#+id/charlie"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/charlie"
android:transitionName="iv1"
android:scaleType="centerCrop"
android:translationZ="0dp"
android:stateListAnimator="#null"
/>
</RelativeLayout>`
Currently, what I see is that the elevation instantly changes at the start of the transition resulting in the dog image to be obscured by the arc.
I checked the github. It's a bug.
I can categorically run the transition between scenes using Transtions and TransitionManager.go(). But, when you run the transition between the fragment and activity it always instantly changes the fade animation. There's a couple fade bugs fixed in Support 26.0.0 beta-1
When a Fade transition is interrupted and reversed, the View starts the animation from the beginning. (Fix ported from Android Framework.)
Transition.Fade ignores initial alpha of View (AOSP issue 221820)
But, ask yourself, with all your fiddling did you ever see it do an actual fade transition? -- No. Like ignore all the moving and whatever, can you get it to do a fade at all? Because that's all my suggestion needed and I can't get it running the way you have it running. But, obviously all the moving of the elements does work so it's a damned bug.
You can totally fake it too. If you had fades, you could just invoke it and get it to work. You get the correct animation if you change the onCreate() in the Activity2 to be:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
setContentView(R.layout.activity2);
findViewById(R.id.arc1).setVisibility(View.VISIBLE);
findViewById(R.id.arc2).setAlpha(0);
findViewById(R.id.arc2).animate().alpha(1).setDuration(2000).start();
}
I only set the visibility of that arc1 to the correct one because you had it wrong. That's the one that is always visible.
I think then add an animation for the same time period as the other one to phase it in, and boom. It works. It's a stupid bug. You can't get fades between activity for no good reason at all.
I discovered the alpha one myself. The first one might be what's happening. Or it could be a different class of bug altogether. But, I can assure you. I checked and did everything right. And it still failed. Obviously the work around would be to use a scene transition where they work. Perhaps not using a new activity as such at all.
There's a bunch of workarounds you could obviously come up with. Just launch the activity with the layout it's supposed to have then setup a scene to transition to the proper layout. Add in another transition to the layout yourself in the first activity. Or whatnot. But, it doesn't work. You do that transition from the fragment to the activity and the stuff will move but the fade always throws a conniption and refuses. It instantly takes on the visibility of the other view and without alpha working either, there's no way to rectify that easily either.
My original code that had something working was using scenes:
boolean to = true;
public void onClick(View view) {
Scene scene;
ViewGroup mSceneRoot = (ViewGroup) findViewById(R.id.container);
if (to) {
Transition mFadeTransition =
TransitionInflater.from(this).
inflateTransition(R.transition.transitionset);
scene = Scene.getSceneForLayout(mSceneRoot, R.layout.fragment_replacement, this);
TransitionManager.go(scene, mFadeTransition);
}
else {
Transition mFadeTransition =
TransitionInflater.from(this).
inflateTransition(R.transition.backwardstransitionset);
scene = Scene.getSceneForLayout(mSceneRoot, R.layout.fragment_rep, this);
TransitionManager.go(scene, mFadeTransition);
}
to = !to;
}
Leaving bits of old answer when I figured it was his fault for being unable to implement my clearly very brilliant idea of how to do the transition. The bug is he has no damned fade that works, and that was always the problem.
You cannot animate that merely with Z order. You change the order and they draw on top of each other rather than the other way around. To do what you're suggesting what you need to do is effectively have both orders at the same time and animate their transition with transparency.
You draw, Arc, Dog, another Arc. Then the variation in the Z-order is literally the transparency of the Arc drawn on top. If it is entirely opaque the Arc is on top of the dog. If it's entirely transparent then the Dog is over the Arc. But, if the topmost Arc is partially transparent, it'll look like the dog is melting through the arc, or arc is melting through the dog, depending on how we adjust the transparency. You can pull the same trick elsewhere. Just put the thing in both places. If it's opaque it's covered, but if it's transparent it only show the lowermost arc, and a mix of the arc with the between the objects if partially transparent. At the end of the animation, just put them in the correct order.
So during the Animation, you move the 2 Arcs to the same position always. You should see them as the same arc. And change the opacity of the Arc on top, and do whatever you're doing with that dog.
Video:
https://youtu.be/zVs3qzPU2FM
Create the layouts. Sandwich the bit you want to change height between two copies of the other object. In the one of the layouts, set the visibility to invisible. So all items are in both layouts in the same order. But, in one, the second copy of the element in question is invisible. Make sure the two copies are in the same position in both. When you change the bounds of one copy, make sure you also change the bounds of the other. Move them as a unit. When you transition the views, fade the item out while moving it around or whatnot. Since there's a second copy it won't look like a fade out, it'll look like a melt-through.
I have a question regarding the android layout transition framework. In particular i want to achieve an effect that a certain part of an layout slides down or up depending on the visibility of another view(s).
Imagine the following layout. (And please overlook the nested LinearLayouts here ;) )
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="#+id/changingView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"/>
<View
android:id="#+id/changingView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"/>
</LinearLayout>
<LinearLayout
android:id="#+id/movingView"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="false"/>
</LinearLayout>
Now what i want to achieve is that when changingView1 and changingView2 change their visibility that movingView slides up or down.
By enabling the LayoutTransition.CHANGING for the parent layout the sliding part works fine so. But this has the side effect that the movingView will also be animated when there are being items added or removed because this layout changes its bounds. And here lies my problem because this results in a very strange looking animation.
So back to my question. Is there a way to keep the sliding animation without animating layout bound changes on the movingView?
Disabling layoutTransitions on the movingView obviously does not help because this only effects the animations of the child views. I also tried playing around with enabling and disabling different LayoutTransitions on the parent layout but so far without the desired effect.
If i can add more details please let me know otherwise i hope someone can help me out.
Thanks in advance!
I know it's late but hope it can help someone. Since android:animateLayoutChanges is the property of the direct parent, you can wrap your View/Layout in a FrameLayout (or some other ViewGroup) and set android:animateLayoutChanges="false" on the new parent.
To avoid unwanted animations you can remove the animate layout changes by code when needed, something like this:
//removing the animate layout changes to prevent the default animation for the newly added items
parentLayout.setLayoutTransition(null);
/* do some logic to add the new views */
//add the animate layout changes back so the over changes will be still animated
new Handler().post(() -> {parentLayout.setLayoutTransition(new LayoutTransition());});
I have been searching for an answer to this for days, and while some things kinda work (and most don't), I'm hoping I can find the best practice for what I'm trying to do.
I'm trying to get a notification bar to display in my app. Ideally, it would slide down from the top, while shifting other elements in the layout to accommodate. Here's an illustration to help: illustration
Here is how the layout is structured (I took out a bit for brevity):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false">
<!-- notification -->
<RelativeLayout
android:id="#+id/notification_bar"
android:layout_width="match_parent"
android:layout_height="40dip"
android:background="#drawable/notification_background"
android:visibility="visible">
<!-- end notifcation -->
</RelativeLayout>
<!-- header -->
<RelativeLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="47dip"
android:layout_alignParentTop="true" >
<ImageView
android:id="#+id/header_bg"
android:layout_width="match_parent"
android:layout_height="47dip"
android:src="#drawable/home_header" />
<!-- end header -->
</RelativeLayout>
<!-- buttons -->
<LinearLayout
android:id="#+id/buttons"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/footer"
android:layout_below="#id/notification_bar"
android:layout_gravity="center_horizontal">
<ImageButton
android:id="#+id/button1"
android:src="#drawable/button1"
android:layout_width="86dip"
android:layout_height="65dip"
android:layout_weight=".4" />
<ImageButton
android:id="#+id/button2"
android:src="#drawable/button2"
android:layout_width="98dip"
android:layout_height="73dip"
android:layout_weight=".2" />
<ImageButton
android:id="#+id/button3"
android:src="#drawable/button3"
android:layout_width="86dip"
android:layout_height="71dip"
android:layout_weight=".4" />
<!-- end buttons -->
</LinearLayout>
<!-- footer -->
<LinearLayout
android:id="#id/footer"
android:layout_width="match_parent"
android:layout_height="76dip"
android:layout_alignParentBottom="true"
android:background="#drawable/home_footer" >
<!-- end footer -->
</LinearLayout>
</RelativeLayout>
MAIN PROBLEM:
To start, I animated the notification bar. It moves, and at the end of the animation, it snaps back into place. Yes, I have fillAfter set to true. It doesn't make a difference. Regardless, the 3 items that should shift are clickable, and from what I've read, the elements haven't actually moved, they just look like they have.
SECONDARY PROBLEM:
The entire view is a RelativeLayout, however the three elements are in a LinearLayout set via the XML to be layout_below the notification bar. I had hoped that shifting the notification bar would squeeze this LinearLayout, shifting the buttons to accommodate, but no such luck. If I have to shift the three elements as separate animations, that's fine. I've tried that, but they suffer from the same "snap-back" issue the notification bar does. I was hoping there would be a simpler, more logical approach, however.
I've found a number of posts about this snap-back problem, but none of the solutions quite work (or make sense to me, granted a bit of a noob). It sounds like something needs to happen in the onAnimationEnd handler. I think it's something with adjusting the LayoutParams, but I'm not sure how or what to do there.
I'm targeting for API 8 (2.2), so the Honeycomb animation APIs won't help. I've looked into NineOldAndroids, which looks promising, but figure there has got to be a way to do this with the native API.
** Bonus points if we can get the notification bar to be dismissed, and everything moves back to its original position.
** UPDATE: The following code KIND OF works **
Here is the animation method to slide the notification bar out:
private void showNotification() {
mNotificationBar.setVisibility(View.VISIBLE);
Animation slideOut = AnimationUtils.loadAnimation(this, R.anim.slide_notification_out);
slideOut.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
// do nothing
}
#Override
public void onAnimationRepeat(Animation animation) {
// do nothing
}
#Override
public void onAnimationEnd(Animation animation) {
// do SOMETHING
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mNotificationBar.getLayoutParams();
params.addRule(RelativeLayout.BELOW, mHeader.getId());
mNotificationBar.setLayoutParams(params);
mNotificationBar.clearAnimation();
}
});
mNotificationBar.startAnimation(slideOut);
}
Altering the LayoutParams on AnimationEnd keeps the Notification bar in place. AND, when the animation is done, the Buttons layout squeezes to accommodate! BUT, the button layout doesn't smoothly animate like the Notification Bar, it just snaps into place at the end of the animation. Also, the Notification Bar also jumps a bit at the very end of the animation, I'm guessing because the layout is being redrawn. SO CLOSE, but so far.
Snap back problem
You need to define the notification in the final place that you want it to appear in the layout. For you it's probably as the first item in the LinearLayout you refer above. Then you set visibilityto gone.
Finally you use a piece of code similar to the one bellow (I´m using it to animate buttons into the screen):
private void buttonFadeOut() {
linear_layout_buttons.startAnimation(AnimationUtils.loadAnimation(MyMapActivity.this, android.R.anim.slide_out_right));
linear_layout_buttons.setVisibility(View.GONE);
}
private void buttonFadeIn() {
if(linear_layout_buttons.getVisibility() == View.GONE){
linear_layout_buttons.startAnimation(AnimationUtils.loadAnimation(MyMapActivity.this, R.anim.slide_in_right));
linear_layout_buttons.setVisibility(View.VISIBLE);
}
}
Squeeze problem
This one I've never tried with an animation, but you can set the android:layout_weight="1.0" in each one of the items in your relative layout, to split the available space equaly between them (or play with the value to assign diferent space for each).
Regards.
I am facing a quite interesting but annoying error, in my linear layout i have hided another linear layout using margin in negative and when user selects a type from a list i bring layout to front using Translational Animation the error is that the layout comes to front have an edit text which becomes dead and when i scroll (my main layout is surrounded by scroll view) it comes alive and when i stop scrolling it becomes dead again... i really failed to judge why is this happening so guys plz help....
i have also pasted link of video below showing this annoying behavior of my app
http://www.dailymotion.com/video/xlskk8_android-app-edit-text-error_tech
my layout xml inside scroll view is
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:layout_marginTop="-110dip"
android:layout_marginBottom="5dip"
android:id="#+id/notes_editor"
android:orientation="vertical"
>
<EditText
android:id="#+id/enter_note"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:maxLines="2"
android:lines="2">
</EditText>
<Button
android:id="#+id/save_note"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Save" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-10dip"
android:id="#+id/notes_list"
android:orientation="vertical"
>
</LinearLayout>
</LinearLayout>
the empty linear layout below button is used for dynamically adding child views all other things are performing their functionality properly, only the edit text showing this abnormal behavior.
the code used for animation is below
public void animateEditor()
{
slider = new TranslateAnimation(0, 0, 0,180 );
slider.setDuration(1250);
slider.setFillAfter(true);
notes_list.startAnimation(slider);
notes_editor.startAnimation(slider);
}
The problem here was when applying slider.setFillAfter(true); the code animates the image of Views but not the actual Views that's why when I see them after sliding down animation they were (EditText and save button) stuck or you can say dead and not listening to their events because actual Views were there behind the layout and at front it was just their image
The solution I found for that problem is to apply following code:
slider.setFillAfter(false);
slider.setFillBefore(false);
// OR you can directly write
slider.setFillEnabled(false);
And then to show actual views on the new place by setting animation listener and using the following method:
public void onAnimationEnd(Animation a)
Placing the views to new position at the end of animation by using above method. And here still comes another problem of blinking which is due to the problem in android animation listener method which is that it is get called before actually animation ends and causes blinking effect, a tricky solution to it is by putting following line of code at first line of public void onAnimationEnd(Animation a) method.
// in my case animation applied to notes_editor so the code will be
notes_editor.clearAnimation();
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);