2

I have a RelativeLayout within which is a ScrollView and an EditText, and if a user shifts focus to the EditText I want the ScrollView to hide itself until they finish. That part was easy, but I also would like the RelativeLayout to shrink/expand gradually to present a nice transition, rather than snapping open/close.

Here is the code which hides the ScrollView when the EditText gains focus:

private class myCostBoxFocusListener implements View.OnFocusChangeListener {

    public void onFocusChange(View v, boolean hasFocus) {

        ScrollView sView = (ScrollView) ((RelativeLayout)v.getParent().getParent()).getChildAt(1);
        //A bit hacky, I know, but it works.

        if (hasFocus) {
            sView.setVisibility(View.GONE);
        }
        else if(!hasFocus) {
            sView.setVisibility(View.VISIBLE);
        }
    }
}

and this works just fine. However, the code I strung together for trying to animate the open/close isn't working. It's currently causing the ScrollView items to fade in/out over 2 seconds, while the RelativeLayout is still snapping open/closed immediately.

LayoutTransition transition = new LayoutTransition();
ObjectAnimator a1 = ObjectAnimator.ofFloat(null, View.SCALE_Y, 0, 1);
AnimatorSet animator = new AnimatorSet();
animator.setStartDelay(0);
animator.play(a1);
transition.setAnimator(LayoutTransition.CHANGE_APPEARING, animator);
transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, animator);
transition.setDuration(2000);
RelativeLayout rView = (RelativeLayout) dialogNew.findViewById(R.id.ocrmain_group_select_parent);
rView.setLayoutTransition(transition);

I've tried using LayoutTransition_APPEARING/DISAPPEARING instead of CHANGE_, but that doesn't animate what I want. I'm clearly missing the concept here, and would greatly appreciate some pointers on how I'm conceptualizing this incorrectly.

mikeappell
  • 363
  • 4
  • 17

1 Answers1

3

Have you tried the built-in layout change animation?

android:animateLayoutChanges="true" added to your relative layout should do what you want.

EDIT: To change the duration of the default animation, you can do something like the following.

public class MainActivity extends Activity {

    private ScrollView scrollView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.test);
        super.onCreate(savedInstanceState);

        RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.relative_layout);
        LayoutTransition t = relativeLayout.getLayoutTransition();
        t.setDuration(2000);
        relativeLayout.setLayoutTransition(t);

        scrollView = (ScrollView) findViewById(R.id.scroll_view);

        EditText editText = (EditText) findViewById(R.id.edit_text);
        editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus) {
                    scrollView.setVisibility(View.GONE);
                }
                else {
                    scrollView.setVisibility(View.VISIBLE);
                }
            }
        });
    }
}

test.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/relative_layout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:animateLayoutChanges="true"
                android:padding="5dp" >

    <LinearLayout android:id="@+id/linear_layout"
                  android:orientation="horizontal"
                  android:layout_width="fill_parent"
                  android:layout_height="wrap_content"
                  android:focusable="true" android:focusableInTouchMode="true"
                  android:layout_alignParentTop="true" >

        <EditText android:id="@+id/edit_text"
                  android:gravity="end"
                  android:layout_width="0dp"
                  android:layout_height="wrap_content"
                  android:layout_weight="3"
                  android:selectAllOnFocus="true"
                  android:imeOptions="actionDone"
                  android:inputType="numberDecimal" />

        <EditText android:id="@+id/edit_text2"
                  android:gravity="end"
                  android:layout_width="0dp"
                  android:layout_height="wrap_content"
                  android:layout_weight="3"
                  android:selectAllOnFocus="true"
                  android:imeOptions="actionDone"
                  android:inputType="numberDecimal" />

    </LinearLayout>

    <ScrollView android:id="@+id/scroll_view"
                android:paddingTop="20dp"
                android:gravity="end"
                android:layout_width="fill_parent"
                android:layout_height="180dp"
                android:layout_below="@id/linear_layout" >

        <TableLayout android:id="@+id/table_layout"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content" >

            <TextView android:layout_height="30dp" android:layout_width="match_parent" android:text="TTTT"/>

            <TextView android:layout_height="30dp" android:layout_width="match_parent" android:text="TTTT"/>

            <TextView android:layout_height="30dp" android:layout_width="match_parent" android:text="TTTT"/>

            <TextView android:layout_height="30dp" android:layout_width="match_parent" android:text="TTTT"/>

            <TextView android:layout_height="30dp" android:layout_width="match_parent" android:text="TTTT"/>

            <TextView android:layout_height="30dp" android:layout_width="match_parent" android:text="TTTT"/>

            <TextView android:layout_height="30dp" android:layout_width="match_parent" android:text="TTTT"/>


        </TableLayout>

    </ScrollView>

    <Button android:id="@+id/button_cancel"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:text="Cancel"
            android:layout_below="@id/scroll_view"
            android:layout_alignParentLeft="true" />

    <Button android:id="@+id/button_ok"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:text="Ok"
            android:layout_below="@id/scroll_view"
            android:layout_alignParentRight="true" />

</RelativeLayout>
mpkuth
  • 6,994
  • 2
  • 27
  • 44
  • That has a somewhat nicer effect, but the size of the window is still changing almost instantly. How do I set a duration for it to expand/contract over? – mikeappell Dec 13 '14 at 06:22
  • Take a look at http://developer.android.com/reference/android/view/ViewGroup.html#setLayoutTransition(android.animation.LayoutTransition). To modify that default transition you might be able to do `t = getLayoutTransition()`, then `t.setDuration(CHANGE_DISAPPEARING, duration)`, then `setLayoutTransition(t)`? – mpkuth Dec 13 '14 at 06:31
  • Ok, here's the problem: what's actually being animated is the buttons which are vanishing/reappearing. The window containing them is still changing size near-instantaneously. Am I applying the transition to the wrong object somehow? – mikeappell Dec 13 '14 at 06:41
  • You may need to use `animateLayoutChanges` and/or `setLayoutTransition` on the parent of the RelativeLayout, since I believe those are telling the system to animate changes to the layout _inside_ the view where that is set. – mpkuth Dec 13 '14 at 06:47
  • See, the RelativeLayout is the topmost View though, thus my confusion. Here's my entire XML file: http://pastebin.com/yA8RFWHG I really need to get some sleep though. Thanks for taking the time; I'll check back in the morning =) – mikeappell Dec 13 '14 at 06:51
  • OK, I just slightly modified that for an easy example locally and I see the following: On focus the buttons move up slowly over the text in the scroll view which fades out slowly. I think you are seeing an immediate height change because the ScrollView is fixed height and just fading in. You might be able to use maxHeight combined with a layout_height of wrap_content and then add/remove items from the table layout on focus/de-focus to achieve what you want. – mpkuth Dec 13 '14 at 07:47
  • Or see http://stackoverflow.com/questions/18582310/android-grow-linearlayout-using-animation for a possible animation solution for APPEARING. – mpkuth Dec 13 '14 at 07:50
  • Upon a lot of reflection, I ended up going with a method that meeds my needs without changing the size of the window. However, as I really want to better understand this, I'm going to read the documentation you've provided so I can get it right next time. Many thanks =) – mikeappell Dec 13 '14 at 23:59