How to animate overlay an edit-box on tab-layout on android?
Asked Answered
F

1

5

I wanted to achieve this animation, which is the search edit box overlays the tab-layout, I must tell that I tried this code on the parent layout android:animateLayoutChanges="true" and set the tab-layout visibility to View.GONE but it just animates the tab moving up, not the search box overlays tab-layout.

enter image description here

Frederique answered 3/11, 2016 at 19:13 Comment(0)
C
8

I have made a quick dummy app that looks like yours, and tried to achieve what you have shown in your animation. See the effect below (you can make it more smooth and elegant) :

enter image description here

Its a bit tricky way of doing, the way I have done. I post my whole code here :

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.pabhinav.testapp3">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


MainActivity.java
package com.pabhinav.testapp3;

import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.LinearInterpolator;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import static com.pabhinav.testapp3.R.id.container;

public class MainActivity extends AppCompatActivity implements PlaceholderFragment.OnSearchBoxClick{

    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a
     * {@link FragmentPagerAdapter} derivative, which will keep every
     * loaded fragment in memory. If this becomes too memory intensive, it
     * may be best to switch to a
     * {@link android.support.v4.app.FragmentStatePagerAdapter}.
     */
    private SectionsPagerAdapter mSectionsPagerAdapter;

    /**
     * The {@link ViewPager} that will host the section contents.
     */
    private ViewPager mViewPager;

    /**
     * Search Box in activity.
     */
    private RelativeLayout dummySearchBox;

    private LinearLayout topSearchBox;

    /**
     * Overlay View appears when search box is clicked.
     */
    private View overlay;

    /**
     * Back button image view for top search box
     */
    private ImageView backButtonSearchBox;

    /**
     * PlaceHolderFragment saved only for second tab,
     * which has search box.
     */
    private PlaceholderFragment placeholderFragment;

    private float xDelta, yDelta;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
        getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));
        overlay = findViewById(R.id.overlay_whole_page);
        backButtonSearchBox = (ImageView)findViewById(R.id.search_icon);

        // Consume touch event, so that it does not pass to parent views.
        // This is done to block swipe events of tab layout, once search
        // box is clicked.
        overlay.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });

        // TabLayout and ViewPager.
        final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
        mViewPager = (ViewPager) findViewById(container);
        dummySearchBox = (RelativeLayout)findViewById(R.id.dummy_search_box);
        topSearchBox = (LinearLayout)findViewById(R.id.top_search_box);

        // Set up the ViewPager with the sections adapter.
        mViewPager.setAdapter(mSectionsPagerAdapter);
        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

            @Override
            public void onPageSelected(int position) {
                for (int i = 0; i < tabLayout.getTabCount(); i++) {
                    if(i == position){
                        tabLayout.getTabAt(i).setIcon(getTabIconHighlighted(i));
                    } else {
                        tabLayout.getTabAt(i).setIcon(getTabIconUnhighlighted(i));
                    }
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {}
        });

        // Setup viewpager with tablayout and also set up icons of each tabs :
        tabLayout.setupWithViewPager(mViewPager);
        for(int i = 0; i<tabLayout.getTabCount(); i++){

            // Set first tab highlighted :
            if(i == 0){
                tabLayout.getTabAt(i).setIcon(getTabIconHighlighted(i));
            } else {
                tabLayout.getTabAt(i).setIcon(getTabIconUnhighlighted(i));
            }
        }

        // Back Button in top search box clicked.
        backButtonSearchBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                overlay.setVisibility(View.INVISIBLE);
                dummySearchBox.setVisibility(View.VISIBLE);
                topSearchBox.setVisibility(View.INVISIBLE);

                AnimationSet animSet = new AnimationSet(true);
                animSet.setFillAfter(false);
                animSet.setDuration(150);
                animSet.setInterpolator(new LinearInterpolator());
                TranslateAnimation translate = new TranslateAnimation(-xDelta, 0, -yDelta, 0);
                animSet.addAnimation(translate);
                ScaleAnimation scale = new ScaleAnimation(1.2f, 1f, 1.2f, 1f);
                animSet.addAnimation(scale);
                dummySearchBox.startAnimation(animSet);
                animSet.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        placeholderFragment.showSearchLayout();
                        dummySearchBox.setVisibility(View.INVISIBLE);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });
            }
        });
    }

    private int getTabIconUnhighlighted(int position){
        switch (position){
            case 0 : return R.drawable.ic_home_black_24dp;
            case 1 : return R.drawable.ic_search_black_24dp;
            case 2 : return R.drawable.ic_heart_black_24dp;
            case 3 : return R.drawable.ic_view_headline_black_24dp;
        }
        return -1;
    }

    private int getTabIconHighlighted(int position){
        switch(position){
            case 0 : return R.drawable.ic_home_highlighted_24dp;
            case 1 : return R.drawable.ic_search_highlighted_24dp;
            case 2 : return R.drawable.ic_heart_highlighted_24dp;
            case 3 : return R.drawable.ic_view_headline_highlighted_24dp;
        }
        return -1;
    }

    /**
     * This event is when search box from fragment is clicked,
     * need to animate the search box present in activity
     * to reach the top of activity display.
     */
    @Override
    public void onClick() {
        dummySearchBox.setVisibility(View.VISIBLE);
        dummySearchBox.clearFocus();
        ((EditText)findViewById(R.id.search_edit_text)).clearFocus();
        performAnimation(dummySearchBox);
    }

    public void performAnimation(final RelativeLayout dummySearchBox){

        if(xDelta == 0 && yDelta == 0){
            DisplayMetrics dm = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(dm);
            int[] originalPos = new int[2];
            dummySearchBox.getLocationOnScreen(originalPos);

            xDelta = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 18, getResources().getDisplayMetrics());
            yDelta = originalPos[1] - TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getResources().getDisplayMetrics());;
        }

        AnimationSet animSet = new AnimationSet(true);
        animSet.setFillAfter(false);
        animSet.setDuration(200);
        animSet.setInterpolator(new LinearInterpolator());
        TranslateAnimation translate = new TranslateAnimation( 0, -1*xDelta, 0, -1*yDelta);
        animSet.addAnimation(translate);
        ScaleAnimation scale = new ScaleAnimation(1f, 1.15f, 1f, 1.15f);
        animSet.addAnimation(scale);
        dummySearchBox.startAnimation(animSet);
        animSet.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {

                topSearchBox.setVisibility(View.VISIBLE);
                dummySearchBox.setVisibility(View.INVISIBLE);
                overlay.setVisibility(View.VISIBLE);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
    }

    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        public static final String ARG_SECTION_NUMBER = "section_number";

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            // getItem is called to instantiate the fragment for the given page.
            // Return a PlaceholderFragment.
            PlaceholderFragment placeholderFragment = new PlaceholderFragment();
            placeholderFragment.setOnSearchBoxClick(MainActivity.this);
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, position + 1);
            placeholderFragment.setArguments(args);
            if(position == 1){
                MainActivity.this.placeholderFragment = placeholderFragment;
            }
            return placeholderFragment;
        }

        @Override
        public int getCount() {
            // Show 4 total pages.
            return 4;
        }
    }
}

PlaceholderFragment.java

package com.pabhinav.testapp3;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * @author pabhinav
 */

public class PlaceholderFragment extends Fragment {

    private LinearLayout searchLayout;

    public PlaceholderFragment() {
    }

    private OnSearchBoxClick onSearchBoxClick;
    public void setOnSearchBoxClick(OnSearchBoxClick onSearchBoxClick){
        this.onSearchBoxClick = onSearchBoxClick;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        int sectionNumber = getArguments().getInt(MainActivity.SectionsPagerAdapter.ARG_SECTION_NUMBER);
        View rootView = inflater.inflate((sectionNumber == 2) ? R.layout.fragment_search : R.layout.fragment_main, container, false);
        if(sectionNumber != 2) {
            TextView textView = (TextView) rootView.findViewById(R.id.section_label);
            textView.setText(getString(R.string.section_format, sectionNumber));
        } else {

            // Its the fragment with search box :
            TextView searchText = (TextView) rootView.findViewById(R.id.search_text);
            ImageView searchIcon = (ImageView)rootView.findViewById(R.id.search_icon);
            searchLayout = (LinearLayout)rootView.findViewById(R.id.search_linear_layout);

            // Need to do transition when clicked on any of the search box elements :
            View.OnClickListener clickListener = new View.OnClickListener(){
                @Override
                public void onClick(View v) {
                    searchLayout.setVisibility(View.INVISIBLE);
                    if(onSearchBoxClick != null)
                        onSearchBoxClick.onClick();
                }
            };
            searchText.setOnClickListener(clickListener);
            searchLayout.setOnClickListener(clickListener);
            searchIcon.setOnClickListener(clickListener);
        }
        return rootView;
    }

    public void showSearchLayout(){
        searchLayout.setVisibility(View.VISIBLE);
    }

    public interface OnSearchBoxClick{
        public void onClick();
    }
}


activity_main.xml
<?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/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.pabhinav.testapp3.MainActivity">

    <android.support.design.widget.TabLayout
        android:layout_marginTop="8dp"
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <!-- Top Search Box -->
    <!-- Only appears when search box is clicked -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:id="@+id/top_search_box"
        android:visibility="invisible"
        android:orientation="horizontal">

        <RelativeLayout
            android:layout_gravity="center"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/white">

            <ImageView
                android:gravity = "center"
                android:layout_width="52dp"
                android:paddingLeft="24dp"
                android:paddingRight="8dp"
                android:id="@+id/search_icon"
                android:layout_height="match_parent"
                android:src="@drawable/ic_arrow_back_black_24dp"/>

            <EditText
                android:layout_toEndOf="@+id/search_icon"
                android:hint="@string/search_soundcloud"
                android:textSize="18sp"
                android:background="@android:color/transparent"
                android:textColorHint="#B3B3B3"
                android:layout_margin="4dp"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

        </RelativeLayout>

    </LinearLayout>

    <!-- Dummy container for search box -->
    <!-- This will do transition from its location to top_search_box location -->
    <RelativeLayout
        android:id="@+id/dummy_search_box"
        android:layout_width="match_parent"
        android:layout_below="@+id/tabs"
        android:visibility="invisible"
        android:layout_height="wrap_content"
        android:padding="16dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:id="@+id/search_linear_layout_dummy"
            android:orientation="horizontal">

            <RelativeLayout
                android:layout_gravity="center"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"
                android:background="@android:color/white"
                android:elevation="2dp"
                android:translationZ="2dp">

                <ImageView
                    android:gravity = "center"
                    android:layout_width="20dp"
                    android:layout_marginStart="16dp"
                    android:id="@+id/search_icon_dummy"
                    android:layout_height="match_parent"
                    android:src="@drawable/ic_search_light_black_24dp"/>

                <EditText
                    android:id="@+id/search_edit_text"
                    android:layout_toEndOf="@+id/search_icon_dummy"
                    android:hint="@string/search_soundcloud"
                    android:textSize="16sp"
                    android:background="@android:color/transparent"
                    android:textColorHint="#B3B3B3"
                    android:layout_margin="4dp"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" />

            </RelativeLayout>

        </LinearLayout>

    </RelativeLayout>


    <android.support.v4.view.ViewPager
        android:layout_below="@+id/tabs"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


    <!-- Dummy overlay over whole page, More things can be added like listview
         which displays result of searched text -->
    <View
        android:id="@+id/overlay_whole_page"
        android:layout_below="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone"
        android:background="#72000000" />

    <!-- Dummy shadow below tablayout -->
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_below="@+id/tabs"
        android:background="#42000000" />



</RelativeLayout>

fragment_search.xml

<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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.pabhinav.testapp3.MainActivity$PlaceholderFragment">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:id="@+id/search_linear_layout"
        android:orientation="horizontal">

        <RelativeLayout
            android:layout_gravity="center"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:elevation="2dp"
            android:translationZ="2dp">

            <ImageView
                android:gravity = "center"
                android:layout_width="20dp"
                android:layout_marginStart="16dp"
                android:id="@+id/search_icon"
                android:layout_height="match_parent"
                android:src="@drawable/ic_search_light_black_24dp"/>

            <TextView
                android:id="@+id/search_text"
                android:layout_toEndOf="@+id/search_icon"
                android:text="@string/search_soundcloud"
                android:gravity="center_vertical"
                android:textColor="#B3B3B3"
                android:textSize="16sp"
                android:layout_margin="4dp"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

        </RelativeLayout>

    </LinearLayout>

    <TextView
        android:id="@+id/suggested_stations"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="56dp"
        android:textSize="18sp"
        android:layout_below="@+id/search_linear_layout"
        android:text = "@string/suggested_stations"/>

    <LinearLayout
        android:layout_below="@+id/suggested_stations"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageView
            android:layout_width="0dp"
            android:layout_height="240dp"
            android:src="@drawable/image_1"
            android:layout_weight="1"/>

        <ImageView
            android:layout_marginStart="16dp"
            android:layout_width="0dp"
            android:layout_height="240dp"
            android:src="@drawable/image_2"
            android:layout_weight="1"/>

    </LinearLayout>

</RelativeLayout>


Download the whole project from here : https://drive.google.com/file/d/0B_Mi44NWLWmyNFNkeHJ6cVBLTTg/view?usp=sharing

Hope it helps !

Candie answered 21/11, 2016 at 19:6 Comment(3)
A already implemented the search box and tab layout, and all that, I just want the animation segment, thanx for your time, flag upFrederique
The animation is bit hacky, you can run the whole project to see if the animation is what you expected, and to find out how I did it, you just need to look at MainActivity.java file.Candie
Ok, I will fry it in the moment, thank you for your time.Frederique

© 2022 - 2024 — McMap. All rights reserved.