Showing posts with label indexer. Show all posts
Showing posts with label indexer. Show all posts

Animated Indexer in Xamarin.Android

Indexer is a quite common UI element in a list view. Its a integral part of contacts list or list of data which can be segregated by alphabets or numbers. It makes app content organised and searchable.
Animating the indexer can add visual cues that notify the user what's going on in the app and they also add polished look to your app, which gives it a higher quality look and feel.



I will be showing you how to implement the above animation in Xamarin.Android, without needing to add any third party libraries.

So let's get started..............


Step 1: In the layout file add a linear layout and a image view, within a frame layout.The linear layout is going to contain all the indexes as text views. The image view is the thumb which would navigate along the user selected index, to highlight the index selected.

 <FrameLayout 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:id="@+id/Frame_layout"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:background="@android:color/white">
      <LinearLayout
        android:id="@+id/Layout_Cust_Index"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentRight="true"
        android:orientation="vertical"
        android:background="@android:color/transparent"
        android:layout_marginTop="15dp"
        android:layout_gravity="right"
        android:gravity="right">
      </LinearLayout>
    <ImageView 
      android:id="@+id/thumb"
      android:layout_width="50dp"
      android:layout_height="50dp"
      android:src="@mipmap/circle"
     android:visibility="gone"
      android:layout_gravity="right"
      android:gravity="right"
      android:paddingRight="-10dp"
      android:paddingTop="-10dp"
      ></ImageView>
  </FrameLayout>


Step 2: In the activity file set the content view and find the thumb image, the linear layout and the frame layout by reference.






             SetContentView(Resource.Layout.Main);

            _layoutIndex = FindViewById<LinearLayout>(Resource.Id.Layout_Cust_Index);
            _frameLayout = FindViewById<FrameLayout>(Resource.Id.Frame_layout);
            _thumbImage = FindViewById<ImageView>(Resource.Id.thumb);

Step 3: Create a array of text views and populate them with the indexes as text views.

            textViewArray = new TextView[26];
            AddIndexToList();

Step 4:  Create the above method "AddIndexToList", Within which we create text views containing characters from 'A' to 'Z' and add them to the linear layout and the text view array for future reference.


 private void AddIndexToList()
        {
            LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(100, 0, 1);
            int i = 0;
            textViewArray = new TextView[26];
            for (char c = 'A'; c <= 'Z'; c++)
            {
                TextView btnindex = new TextView(this);
                btnindex.LayoutParameters = lparams;
                btnindex.SetPadding(10, 10, 40, 10);
                btnindex.Gravity = GravityFlags.Center;
                btnindex.TextSize = 12;
                btnindex.SetTextColor(Color.Black);
                btnindex.Text = c.ToString();
                _layoutIndex.AddView(btnindex);
                textViewArray[i] = btnindex;
                i++;
            }
            _layoutIndex.BringToFront();
        }


Step 5: Add the touch event handler to the layout index , to intercept the touch event location and animate according to the user touches.



            _layoutIndex.Touch += TouchesInStrip;




Step 6: Add the method 'TouchesInStrip' to handle the touch down, touch up and touches moved events


private void TouchesInStrip(object sender, View.TouchEventArgs e)
        {
            float x = e.Event.GetY();
            switch (e.Event.Action & MotionEventActions.Mask)
            {
                case MotionEventActions.Down:
                    {
                        for (int i = 0; i < 26; i++)
                        {
                            float y = textViewArray[i].GetY();
                            if (Math.Abs(y - x) <= 10)
                            {
                                indexToAnimate = i;
                                EndAnimation();
                                StartAnimation();
                                AnimateThumb(x);
                                indexToEndAnimate = indexToAnimate;
                            }
                        }
                    }
                    break;

                case MotionEventActions.Move:
                    {
                        x = e.Event.GetY();
                        for (int i = 0; i < 26; i++)
                        {
                            float y = textViewArray[i].GetY();
                            if (Math.Abs(y - x) <= 10)
                            {
                                indexToAnimate = i;
                                EndAnimation();
                                StartAnimation();
                                AnimateThumb(x);
                                indexToEndAnimate = indexToAnimate;
                                break;
                            }
                        }
                    }
                    break;

                case MotionEventActions.Up:
                    {
                        InitializeToStart();
                    }
                    break;
                case MotionEventActions.Cancel:
                    {
                        InitializeToStart();
                    }
                    break;
                case MotionEventActions.Outside:
                    {
                        InitializeToStart();
                    }
                    break;
                default:
                    break;
            }
        }


Step 7: Next step is to add the 'StartAnimation' , 'EndAnimation' and the 'AnimateThumb' Methods.
As the name suggests start animation is to animate the indexes or the characters to form a semicircle along the thumb.
End animation is to move the indexes back to their original position.
Animate thumb is to move the thumb image along the user touch locations.



  private void StartAnimation()
        {

            if (indexToAnimate >= 2)
                AnimateOutward(indexToAnimate - 2, -80f, 400);
            if (indexToAnimate >= 1)
                AnimateOutward(indexToAnimate - 1, -120f, 400);

            AnimateOutward(indexToAnimate, -160f, 400);

            if (indexToAnimate + 1 <= 24)
                AnimateOutward(indexToAnimate + 1, -120f, 400);
            if (indexToAnimate + 2 <= 24)
                AnimateOutward(indexToAnimate + 2, -80f, 400);
        }


To animate it outward we provide the view to animate, the x offset to move outward and the duration of animation.

Here we animate the index at the touch location and two indexes to the top and bottom of the location so that it forms a semi circle





End Animation method animates the x translation to original location i.e; 0


 private void EndAnimation()
        {
            _thumbImage.Visibility = ViewStates.Gone;

            for (int i = 0; i < 26; i++)
            {
                if (i != indexToAnimate && i != indexToAnimate - 1 && i != indexToAnimate - 2 &&
                    i != indexToAnimate + 1 && i != indexToAnimate + 2)
                {
                    AnimateOutward(i, 0f, 200);
                }
            }
        }


Animate  Thumb moves the thumb image to the user touch location


 private void AnimateThumb(float y)
        {
            _thumbImage.Visibility = ViewStates.Visible;
            ObjectAnimator animation = ObjectAnimator.OfFloat(_thumbImage, "translationY", y );
            animation.SetDuration(10);
            animation.Start();
        }


Step 8: Add the 'AnimateOutward' method to animate the view x translate. This method uses the object animator to animate the given view to a given x translate in a given duration of time.


 private void AnimateOutward(int index, float value, int duration)
        {
            ObjectAnimator animation = ObjectAnimator.OfFloat(textViewArray[index], "translationX", value);
            animation.SetDuration(duration);
            animation.Start();
        }


Step 9: Add the final method to animate all the indexes back to position. This method scans through each index and positions them to their original location when the user touches end.


  private void InitializeToStart()
        {
            for (int i = 0; i < 26; i++)
            {
                AnimateOutward(i, 0f, 0);
            }
        }


The animation methods are called based on the touch events and this animates the thumb and the indexes based on the user touches.


I hope you enjoyed this blog..... Please feel to download the sample project from here.

Popular Posts