Best Way to Make an Expander Using Animation

Nathan Sokalski 4,116 Reputation points
2021-03-09T22:56:33.72+00:00

I am working on making an Expander-like control (well, it's not really a control, but anyway) by using an animation. Because the content (the part that gets hidden or revealed) has an unknown height (actually, the height may be different at different times), I am trying to figure what property(s) to animate. If there was a clip property for which I could set a % (which would be animated between 0 & 100), that would be nice, but one of the challenges for my scenario is that setting a fixed height would prevent resizing when the content changes. Any suggestions? Thanks.

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,296 questions
{count} votes

2 answers

Sort by: Most helpful
  1. JarvanZhang 23,951 Reputation points
    2021-03-12T08:30:42.39+00:00

    I created a basic demo to test the function, the layout's height will be updated when the hidden imageView becomes visible. Here is the related code, you could refer to:

    layout.xaml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"    
            android:orientation="vertical">
        <LinearLayout
            android:id="@+id/layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <Button
                android:id="@+id/btn1"
                android:text="button1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
            <EditText
                android:hint="edit test"
                android:gravity="center_horizontal"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
            <Button
                android:id="@+id/btn2"
                android:text="button2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
            <ImageView 
                android:id="@+id/img"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/grid_"
                android:visibility="gone"/>
        </LinearLayout>
    </LinearLayout>
    

    Activity.cs

    public class Activity1 : Activity
    {
        Button btn1;
        Button btn2;
        LinearLayout layout;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
    
            SetContentView(Resource.Layout.layout1);
            // Create your application here
            btn1 = FindViewById<Button>(Resource.Id.btn1);
            btn2 = FindViewById<Button>(Resource.Id.btn2);
            btn1.Click += Btn1_Click;
            btn2.Click += Btn2_Click; ;
            layout = FindViewById<LinearLayout>(Resource.Id.layout);
        }
    
        private void Btn1_Click(object sender, EventArgs e)
        {
            Console.WriteLine("Layout's Height: " + layout.Height);
        }
        private void Btn2_Click(object sender, EventArgs e)
        {
            var img = FindViewById<ImageView>(Resource.Id.img);
            if (img.Visibility == ViewStates.Gone)
            {
                img.Visibility = ViewStates.Visible;
            }
            else
            {
                img.Visibility = ViewStates.Gone;
            }
        }
    }
    

  2. JarvanZhang 23,951 Reputation points
    2021-03-17T07:34:06.1+00:00

    You could use the handler to add the delay for the UI rendering. And try using a layout to wrap the imageView, when I test the function, the imageView's height will not be null when it's Visibility is set from Visible to Gone.

    Check the code:

    //layout.xaml
    <LinearLayout
        android:id="@+id/layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <Button
            android:id="@+id/btn1"
            android:text="button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        ...
        <LinearLayout
            android:id="@+id/imgLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <ImageView 
                android:id="@+id/img"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/grid_"
                android:visibility="gone"/>
                </LinearLayout>
    </LinearLayout>
    
    //function code:
    Handler handler = new Handler(Looper.MainLooper);
    LinearLayout imgLayout;
    private async void Btn2_Click(object sender, EventArgs e)
    {
        imgLayout = FindViewById<LinearLayout>(Resource.Id.imgLayout);
        if (img.Visibility == ViewStates.Gone)
        {
            img.Visibility = ViewStates.Visible;
            handler.PostDelayed(() =>
            {
                Console.WriteLine("imgLayout's Height: " + imgLayout.Height);
            }, 200);
        }
        else
        {
            img.Visibility = ViewStates.Gone;
            handler.PostDelayed(() =>
            {
                Console.WriteLine("imgLayout's Height: " + imgLayout.Height);
            }, 500);
        }
    }
    
    0 comments No comments