Android listview extra space at the end when scroll - android

I have experienced strange behaviour with smooth scroll on listview.
I have 30 items in list. When I smooth scroll via
listview.smoothScrollToPositionFromTop(29, 0);
there will be some extra space at the end of screen. Actually listview shifts up a little. Image attached below. But if I scroll manually there will be no space. What can be done to resolve this behaviour?
Here is my layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_orange_light">
<ListView
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>

As you have said, I think it's an Android issue. It appears to be part of the animation for over scroll, it seems to get 'stuck' before completing the animation. I've had similar experience with SwipeToRefresh, where the progress indicator doesn't fully disappear after refresh.
Anyway, you can workaround by turning off the animation
listView.setOverScrollMode(View.OVER_SCROLL_NEVER);
Unfortunately, this loses the animation even if manually scrolled. If you can live with that, I think this will fix your problem.
AbsListView#setOverScrollMode(int)
EDIT: (after original answer was accepted)
I have also found another work around. This one preserves the over scroll animation. Unfortunately, it has another drawback. If the user auto scrolls before doing anything else, the same problem of the border at the bottom exists. If the user manually scrolls to the bottom 1st, no problem from then on. If the user auto scrolls and gets the border, then manually scrolls, no more problem. So, here is the alternate method.
Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.invisible_footer, null);
listView.setOverscrollFooter(drawable);
In the drawable folder, "invisible_footer.xml"
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="2dp"
android:width="10dp"
android:viewportWidth="10"
android:viewportHeight="2">
<!-- a horizontal line -->
<path android:pathData="M 1 1 H 10"
android:strokeColor="#00000000" android:strokeWidth="1" />
</vector>
ListView.html#setOverscrollHeader()
This gives choices:
Lose over scroll animation
Retain animation but risk user seeing bottom border 1 time

Did you try to set the height of your ListView to wrap_content instead of match_parent?
Even in [this tutorial] all the attributes are set to wrap_content. So replace your ListView attributes on width and height to:
<ListView
android:id="#+id/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

i have implemented. but, at initial first time it keep the padding at bottom but, from second time its working fine.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.socialintegration.ListAct">
<ListView
android:id="#+id/listTemp"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</RelativeLayout>
CODE :
public class ListAct extends AppCompatActivity {
ListView l;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
String str[] = new String[50];
for (int i = 0; i < 50; i++) {
str[i] = "poistion" + i;
}
ArrayAdapter adpt = new ArrayAdapter(ListAct.this, android.R.layout.simple_dropdown_item_1line, str);
l = (ListView) findViewById(R.id.listTemp);
l.setAdapter(adpt);
l.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
l.smoothScrollToPositionFromTop(29, 0);
}
});
}
}

There is an other SO post link which describes a similar problem. I guess the solution in that post should solve your problem.

try this to your xml:
<ListView
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="0dp"
android:clipToPadding="false"/>

<ListView>
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior/>
Ok so try:
app:layout_behavior="#string/appbar_scrolling_view_behavior"

I strongly believe to move to RecyclerView.
If you don't want to move.
Here is work around. Just add this method to your activity, and call it.
private void smoothScrollToTop(final int pos) {
listView.smoothScrollToPositionFromTop(pos, 0);
listView.post(new Runnable() {
#Override
public void run() {
listView.smoothScrollToPosition(pos);
}
});
}
This is well tested. and worked for me. And here is output.

Related

How can I animate an elevation change as part of a scene change animation/transition?

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.

Make a view in recyclerview cell float above a previous cell

I am using a RecyclerView to show a list of videos.
Each item in the list holds Video and SeekBar (and more stuff actually but not relevant here) in a RelativeLayout, as follows:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/performance"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.my.company.VideoView
android:id="#+id/the_video"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:keepScreenOn="true"
android:scaleType="fitCenter" />
<SeekBar
android:id="#+id/the_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:alpha="1.0"
android:maxHeight="#dimen/seekbar_height"
android:minHeight="#dimen/seekbar_height"
android:padding="0dp"
android:progressDrawable="#drawable/my_progressbar"
android:thumb="#drawable/my_progressbar_circle"
android:translationY="-5dp" />
</RelativeLayout>
As you can see I added a android:translationY property that brings the SeekBar up a little so it would be partially positioned on top of the previous cell, i.e. the previous Video.
However it remains partially hidden. I can only see the part that is in the RelativeLayout in which is it declared.
I tried calling bringToFront() on the seekbar and on the RelativeLayout (performance) itself - but that did not help.
Probably the question is not relevant to RecyclerView only. Being somewhat new in android dev I am not sure if I can place a view that is declared inside a RelativeLayout to show up outside of its borders.
Hope I was clear, need your help. Tx.
By default, every view is clipped to its parent size.
You could try to disable this clipping, by adding this in your RelativeLayout XML attributes:
android:clipChildren="false"
android:clipToPadding="false"
or in code
viewGroup.setClipChildren(false);
viewGroup.setClipToPadding(false);
In your case, it seems that either RecyclerView or LinearLayoutManager consider that previous items should be displayed over following ones. One way could be to use RecycleView decoration to overlap :
recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
private final static int vertOverlap = -10;// TODO : do not forget to convert dp in pixels
#Override
public void getItemOffsets (Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(0, vertOverlap, 0, 0);
}
});
So, you would not need to use translationY on your SeekBar, but rather to add some paddingTop to your VideoView :
android:paddingTop="5dp"
That way, I think you could hide the SeekBar if needed, and cell overlapping would not be visible.
Follow this answer with same case only the difference is it is overlapping next item of Recycleview https://stackoverflow.com/a/40603773/3839498

android which layout for elements side by side

I'm new on android programmation. I want to achieve a simple layout with elements side by side inside a scrollview. The idea is to process a single element per time with image and text, letting the layout choose when its the right time for the carriage return, in dependence of the screen resolution. I tried every type of layout, but no one seems to be suitable for my purpose. Particulary with Relative Layout elements are overlapped, instead what I need is an spatial append. Before to try a workaroud (for example adding more element in a row inside a linear layout) i would to know if exists a more natural solution.
(source: youth-stories.com)
I create an example activity to try the solutions:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final RelativeLayout container = (RelativeLayout)findViewById(R.id.container);
for(int i=0; i < 100; i++)
{
final Button button = new Button(this);
button.setText("sda"+i);
button.setId(i);
container.addView(button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
container.removeView(button);
}
});
}
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="0dp"
android:id="#+id/outer"
android:tileMode="disabled" android:gravity="top">
<ImageView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/background"
android:scaleType="centerCrop"/>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/scrollView" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/container"></RelativeLayout>
</ScrollView>
</RelativeLayout>
From the above fig given, you can use GridView to draw UI as given. You can specify spacing between items also how many columns each row consists.
For reference check developer doc.
Check here for GridView example and doc
For the diagram shown you can go for a Grid Layout, you can customize grid layout for spacing between cells.
If it still doesn't fit your need then, my suggestion would be Linear layout with layout weights,however nested weights are a performance overhead.
http://developer.android.com/reference/android/widget/GridLayout.html
http://androidexample.com/Custom_Grid_Layout_-_Android_Example/index.php?view=article_discription&aid=76&aaid=100
Why are nested weights bad for performance? Alternatives?
Hope this help!!

Smooth hide/show animation for View and a second view filling the empty space

I'm trying to animate a view and hide it after some DP's were scrolled and i made everything fine, but the problem is that it will flick horribly when you are scrolling slowly before or after the Y value that is supposed to trigger the animation.
I think the flick is because i have to set its visibility to Gone and update the other view as match_parent, it won't work with just the TraslationY:
view.animate()
.translationY(-view.getBottom())
.alpha(0)
.setDuration(HEADER_HIDE_ANIM_DURATION)
.setInterpolator(new DecelerateInterpolator());
I tried to set the layout to relative and View 2 as match_parent to see if i could avoid the visibility change but it didn't work...
I have implemented all required code from Google I/O 2014 BaseActivity.java file:
https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/ui/BaseActivity.java#L17
And the animation works... but i assume that, as my customview isn't an actionbar with overlay properties, the customview won't leave and LinearLayout below won't fill the empty space (there is none).
SO, i made it to work with an animationlistener and setting customview visibility to gone when the animation is over but it will flick in a horrible way when you are close to the expected Y point that trigger the animation (flick as customview visibility is gone and LinearLayout below needs to resize itself to fill the empty space, and will quickly repeat if you scroll slowly around there).
XML:
<?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:clickable="false"
android:animateLayoutChanges="true">
<com.project.app.layouts.TabsLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/tabs">
<FrameLayout
android:id="#+id/content_frame_header"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:background="#android:color/white"/>
</LinearLayout>
</RelativeLayout>
Is there any way to do this when it's not an actionbar?
EDIT:
Added the comment about how it will flick when you scroll slowly around Y point that triggers the animation to hide/show.
I recommend you to use android:hardwareAccelerated="true" attribute in your Manifest file. It will use your device's GPU to draw views and animations.
I suggest you to check the value of view.getBottom() in both cases (when it works and when not).
It may be that it flicks because the value returned by view.getBottom() is very big.
Add this line in your code:
Log.i("YourAppName", "view.getBottom(): -" + view.getBottom());
view.animate()
.translationY(-view.getBottom())
.alpha(0)
.setDuration(HEADER_HIDE_ANIM_DURATION)
.setInterpolator(new DecelerateInterpolator());
Then check your log to see if the values are the same or not.
I have made it in a slightly different way. Note that the call I'm using requires SDK 19 (KitKat), but you can still do it using ViewPropertyAnimatorCompat
I have a FrameLayout that has the header view and the main view, with the header view on front.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fab="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<include layout="#layout/main_layout" android:id="#+id/main_layout" />
<include layout="#layout/header_layout" android:id="#+id/header_layout" />
</FrameLayout>
Once the views are measured (posting a runnable during onResume) I set the topPadding of the main view to be the Height of the header.
In the hide and show animation, I add an update listener and inside it I update the top padding of the main view to be the Height of the header + the Translation on Y.
final View header = findViewById(R.id. header_layout);
header.animate()
.translationY(-header.getBottom())
.setDuration(200)
.setInterpolator(new DecelerateInterpolator())
.setUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int top = (int) (header.getHeight()+header.getTranslationY());
findViewById(R.id.main_view).setPadding(0, top, 0, 0);
}
});
This makes it a bit smoother, since the padding gets updated together with the translation.
Actually, setting an AnimationListener using ViewPropertyAnimatorCompat does not work. The listener is never called, so for backwards compatibility I opted for this solution, not elegant, but at least it work on pre-KitKat devices:
final View mainView = findViewById(R.id.main_view);
Runnable mainUpdateRunnable = new Runnable() {
#Override
public void run() {
int top = (int) (header.getHeight()+header.getTranslationY());
mainView.setPadding(0, top, 0, 0);
if (mAnimatingHeader) {
mainView.post(this);
}
}
};
mainView.post(mainUpdateRunnable);
The variable mAnimatingHeader is updated using the AnimationListener (which works)

Android -- Hiding Views

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".

Categories

Resources