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.
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'm implementing a simple flip-clock / counter / ticker widget which will consist of several instances of a following "digit" widget:
It's a digit placed on top of a background image. The digit is supposed to animate every second by sliding up and revealing next digit. During the animation both digits should stay "within" the background's boundary.
I'm trying to achieve this behavior by having a TextView with 2 lines - one digit per line - and animating this TextView's position upwards, until the next digit is fully visible. And then I will reset TextViews position and replace both digits at the same time, so that it's impossible to notice. Then I will repeat the process and make it look like the animation never ends.
Here you can see an intermediate state of the animation, when part of zero and part of nine is visible. I "mocked" it in the Graphical Layout editor of Eclipse, by setting the layout_marginTop property to a negative value.
Here's the layout file (the mentioned attribute is normally not there).
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="20dp"
android:layout_height="38dp"
android:background="#drawable/background_countdown_normal_grey"
android:clipChildren="false" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:paddingBottom="5dp"
android:paddingTop="5dp" >
<TextView
android:id="#+id/textview_countdown_digit"
style="#style/TextView.CountdownDigit"
android:layout_marginTop="-12dp"
android:text="0\n9" />
</LinearLayout>
</LinearLayout>
I tried two solutions. By using ViewPropertyAnimator on either translateY or y, I get a smooth animation, but the original clipping of the TextView does not change during animation, so in effect the second digit is never visible. As you can see, I tried clipChildren property, but it doesn't seem to change anything.
My second approach was to use ValueAnimator with a custom Evaluator, which modifies the topMargin of LayoutParams on the TextView. It works, but the animation is very choppy even on high-end devices.
So my question is, how to avoid view clipping during animation and make so in an efficient way? Is there a better approach?
I found an alternative solution in which I use a ScrollView instead. My layout looks like this:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollview_countdown_digit"
android:layout_width="20dp"
android:layout_height="38dp"
android:background="#drawable/background_countdown_normal_grey"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:scrollbars="none" >
<TextView
android:id="#+id/textview_countdown_digit1"
style="#style/TextView.CountdownDigit"
android:text="0\n9" />
</ScrollView>
I animate using ObjectAnimator by scrollY property. Works well so far.
I also tried having 2 TextViews intsead of one (in my initial layout), but it did not change the fact of clipping.
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();
long time listener, first time caller...
I am creating a splash screen derived from Activity called SplashBase that is placed inside a shared project. The layout is the following:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linlytSplash"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ImageView
android:id="#+id/imgvwSplash"
android:src="#drawable/splashscreen"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
></ImageView>
<LinearLayout
android:id="#+id/linlytProgress"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:gravity="center"
>
<ProgressBar
android:id="#+id/progbarProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
></ProgressBar>
<TextView
android:id="#+id/txtvwProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:gravity="center_vertical"
android:text="#string/loading_ellipsis"
android:textStyle="bold"
></TextView>
</LinearLayout>
</LinearLayout>
I am loading the animations like this :
Animation animation = AnimationUtils.loadAnimation(this, R.anim.splashscreen_anim);
animation.setAnimationListener(new AnimationListener() {
public void onAnimationEnd(Animation animation) {
// Advance to the next screen.
if (null != m_intentToLaunch) {
startActivity(m_intentToLaunch);
}
finish();
}
});
animation.setStartTime(AnimationUtils.currentAnimationTimeMillis() + 1000);
I have a derived class called Splash which lives in my main project.
I've had this splash screen for a long time now, the animation has always worked. My ImageView is shown for 2 seconds, and then animates and disappears before calling finish() and loading the next Activity.
I am now adding a ProgressBar which only be shown for the first second (not exactly, but it's clearer if I explain it that way). For some reason, after I hide the ProgressBar, the animation no longer works on the ImageView. When I call
findViewById(R.id.linlytProgress).setVisibility(View.INVISIBLE);
the animation no longer works. In order to test I have placed the following calls:
findViewById(R.id.txtvwProgress).setVisibility(View.INVISIBLE);
and then
findViewById(R.id.progbarProgress).setVisibility(View.INVISIBLE);
When I hide only the TextView, things work as expected. When I hide the ProgressBar, boom, my ImageView no longer animates. I'm at a loss.
Sounds like a bug to me. Create a sample project that reproduces the error and file a bug with that sample project on http://b.android.com. Be sure to mention on the bug where you're seeing this (particular hardware or emulator version). If you think of it, add a comment to this answer with a link to the bug report.
I finally found the answer to my own question. The view needed to be invalidated.
findViewById(R.id.imgvwSplash).invalidate();
et voila! It works exactly as expected, and so far on every platform that I tried it on.
Thanks to everyone who took a look at the question.
-I_Artist
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".