[JAVA] Personnaliser les onglets avec une animation

introduction

J'ai essayé d'implémenter TabLayout qui s'anime comme ça.

tab_anim.gif

!Mise en garde!

TabLayout + ViewPager

Créez un fichier de mise en page pour l'écran principal avec TabLayout + ViewPager. Pour plus de détails sur l'utilisation de TabLayout et ViewPager, reportez-vous à d'autres articles et officiels.

https://qiita.com/furu8ma/items/1602a4bbed4303fec5b1

Ici, placez simplement TabLayout et ViewPager et contrôlez-les avec MainActivity. En prime, j'ai mis en place la barre de titre en haut.

activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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.hoge.hogeapp.MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_below="@+id/titlebar"
            android:background="@color/color_white1">

            <android.support.design.widget.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="70dp"
                app:tabIndicatorColor="@color/color_green1"
                app:tabMode="scrollable"
                android:background="@android:color/white"
                android:elevation="4dp"
                tools:targetApi="lollipop" />

            <android.support.v4.view.ViewPager
                android:id="@+id/pager"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

        </LinearLayout>

        <include
            android:id="@+id/titlebar"
            layout="@layout/item_titlebar" />

    </RelativeLayout>
</LinearLayout>

Créez un adaptateur et liez-le.

MainActivity.java


MainFragmentPagerAdapter adapter = new MainFragmentPagerAdapter(getSupportFragmentManager());
ViewPager viewPager = findViewById(R.id.pager);
viewPager.setAdapter(adapter);

TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);

Paramètres de l'adaptateur

MainFragmentPagerAdapter.java


package com.hoge.hogeapp;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;


public class MainFragmentPagerAdapter extends FragmentPagerAdapter {

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

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return new FugaFragment();
            case 1:
                return new HogeFragment();
            default:
                return new PiyoFragment();
        }
    }

    @Override
    public CharSequence getPageTitle(int position) { return null; }

    @Override
    public int getCount() { return MainActivity.tabLength; }
}

Puisque le titre de l'onglet est défini par Activity, getPageTitle () doit renvoyer null. Définissez respectivement getItem () et getCount ().

Créer une vue du contenu de TabLayout

Ensuite, définissez le texte et l'icône dans le contenu de TabLayout.

// create TAB1
tabLayout.getTabAt(0).setCustomView(R.layout.item_tab1);
// create TAB2
tabLayout.getTabAt(1).setCustomView(R.layout.item_tab2);
                             :
                             :

Ou

// create TAB1
tabLayout.getTabAt(0).setText(R.string.tab1);
tabLayout.getTabAt(0).setIcon(R.drawable.tab1Icon);
// create TAB2
tabLayout.getTabAt(1).setText(R.string.tab2);
tabLayout.getTabAt(1).setIcon(R.drawable.tab2Icon);
                             :
                             :

Il est plus facile de le définir dans tabLayout comme ceci Je dois faire beaucoup de fichiers de mise en page, Si vous faites setText (), setIcon (), vous ne pourrez pas le gérer à partir du fichier de mise en page, donc ...

Cette fois, gonflez le fichier de mise en page et liez l'image et le texte avec la liaison de données. Après cela, nous définirons la vue liée au tableau de TabLayout.Tab.

LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
TabLayout.Tab[] tab = new TabLayout.Tab[tabLength];
// create TAB1
tab[0] = tabLayout.getTabAt(0);
View tabView = inflater.inflate(R.layout.item_tab, null);

ItemTabBinding binding = ItemTabBinding.bind(tabView);
Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.tab1Icon, null);
binding.setItemTabData(new ItemTabData(drawable, R.string.tab1));

tab[0].setCustomView(tabView);
                               :
                               :

C'est un problème, mais je pense qu'il a une grande évolutivité. Vous pouvez préparer un fichier de mise en page pour chaque onglet,

viewGroup = (ViewGroup) tabLayout.getChildAt(0);
View childView = viewGroup.getChildAt(tabPosition);
ImageView tabIconView1 = (ImageView) childView.findViewById(R.id.tab_icon);
TextView tabTitleView1 = (TextView) childView.findViewById(R.id.tab_title);
                               :
                               :

Obtenir une instance de la vue enfant pour chaque onglet Vous pouvez définir l'animation pour chaque pièce à l'intérieur de l'onglet. Vous pouvez le faire que vous l'utilisiez ou non.

tab_anim2.gif

J'ai essayé de le résumer comme ça.

MainActivity.java


private View[] tabIconView;
private View tabView;
private LayoutInflater inflater;
                               :
                               :
// create tab
TabLayout.Tab[] tab = new TabLayout.Tab[tabLength];
inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
tabIconView = new View[tabLength];
for(int i = 0; i < tabLength; i++) {
    tab[i] = tabLayout.getTabAt(i);
    switch (i) {
        case 0:
            bindTabData(R.drawable.ic_cached, R.string.tab1);
            break;
        case 1:
            bindTabData(R.drawable.ic_alarm, R.string.tab2);
            break;
        case 2:
            bindTabData(R.drawable.ic_notifications, R.string.tab3);
            break;
        case 3:
            bindTabData(R.drawable.ic_android, R.string.tab4);
            break;
        default:
            break;
    }
    tab[i].setCustomView(tabView);
}

MainActivity.java


// create tab dataBinding
private void bindTabData(int drawableRoot, int stringRoot) {
   tabView = inflater.inflate(R.layout.item_tab, null);

   ItemTabBinding binding = ItemTabBinding.bind(tabView);
   Drawable drawable = ResourcesCompat.getDrawable(getResources(), drawableRoot, null);
   binding.setItemTabData(new ItemTabData(drawable, getString(stringRoot)));
}

Définissez tabLength = 4 et créez environ 4 onglets. Il est facile de voir si vous faites de la partie DataBinding une méthode et prenez le fichier de ressources que vous souhaitez lier à l'argument.

Ensuite, nous avons besoin d'un fichier de mise en page d'onglet, un modèle de DataBinding, alors ajoutez-le. Voir d'autres pour la liaison de données recommandée

https://qiita.com/Omoti/items/a83910a990e64f4dbdf1

item_tab.xml


<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.hoge.hogeapp.MainActivity">

    <data>
        <variable name="itemTabData" type="com.hoge.hogeapp.MainActivity.ItemTabData" />
    </data>

    <RelativeLayout
        android:id="@+id/item_tab"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="80dp"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:background="@drawable/tab_color_selector">

            <ImageView
                android:id="@+id/tab_icon"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginTop="12dp"
                android:src="@{itemTabData.tabIcon}"
                android:layout_gravity="center" />

            <TextView
                android:id="@+id/tab_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="4dp"
                android:text="@{itemTabData.tabTitle}"
                android:layout_gravity="center"
                android:textColor="@color/color_green1"
                android:textSize="12sp" />

        </LinearLayout>
    </RelativeLayout>
</layout>

MainActivity.java


public class ItemTabData {
    private Drawable tabIcon;
    private String tabTitle;

    private ItemTabData(Drawable tabIcon, String tabTitle) {
        this.tabIcon = tabIcon;
        this.tabTitle = tabTitle;
    }

    public Drawable getTabIcon() {
        return tabIcon;
    }
    public void setTabIcon(Drawable tabIcon) {
        this.tabIcon = tabIcon;
    }

    public String getTabTitle() {
        return tabTitle;
    }
    public void setTabTitle(String tabTitle) {
        this.tabTitle = tabTitle;
    }
}

N'oubliez pas de l'ajouter à build.gradle

build.gradle


dataBinding {
    enabled = true
}

À ce stade, la génération des onglets est terminée.

Définir une animation dans Listener

Ensuite, je voudrais définir l'animation. Et avant ça

MainActivity.java


// get tabs instance
viewGroup = (ViewGroup) tabLayout.getChildAt(0);
for(int tabPosition = 0; tabPosition < tabLength; tabPosition++) {
    View childView = viewGroup.getChildAt(tabPosition);
    tabIconView[tabPosition] = (View) childView.findViewById(R.id.tab_icon);
}

Obtenez la vue que vous souhaitez animer à partir de l'ID de la vue enfant pour chaque onglet sous forme de tableau. Déclarez tabLayout et viewGroup en tant que variables membres afin de pouvoir y accéder à partir de l'activité.

Ensuite, à partir des paramètres de l'auditeur

tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
    @Override
    public void onTabSelected(TabLayout.Tab tab) {
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
    }

    @Override
    public void onTabReselected(TabLayout.Tab tab) {
    }
});

Il semble préférable d'utiliser addOnTabSelectedListener. * Version 26.1.0 ou ultérieure Vous pouvez maintenant étendre TabLayout.OnTabSelectedListener. Ajoutons maintenant une animation à chaque rappel.

MainActivity.java


tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        int position = tab.getPosition();
        switch (position) {
            case 0:
                Animation tabAnimation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.roll_anim);
                tabIconView[0].startAnimation(tabAnimation);
                break;
            case 1:
                Animation tabAnimation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.updown_anim);
                tabIconView[1].startAnimation(tabAnimation);
                break;
                               :
                               :
        }
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
        int position = tab.getPosition();
        switch (position) {
            case 0:
                tabIconView[0].setAnimation(null);
                break;
            case 1:
                tabIconView[1].setAnimation(null);
                break;
                               :
                               :
        }
    }

    @Override
    public void onTabReselected(TabLayout.Tab tab) {
    }
});

Je pense qu'il serait bien de démarrer l'animation de la vue acquise lorsque chaque onglet est sélectionné et de l'arrêter lorsque l'état sélectionné se termine. Commençons par le fichier de mise en page. Créez un dossier anim sous le dossier res et créez-le dedans. Implémentez-en un simple en utilisant View Animation. Je l'ai fait comme un échantillon comme celui-ci. Voir d'autres pour l'animation Recommandé

https://qiita.com/BingSyu/items/bd1278feab270501330b

roll_anim.xml


<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <rotate
        android:duration="800"
        android:fromDegrees="0"
        android:toDegrees="360"
        android:pivotX="50%"
        android:pivotY="50%"
        android:startOffset="200"
        android:repeatMode="restart"
        android:repeatCount="-1" />
</set>

Si vous souhaitez gérer de l'activité

// composite animation
AlphaAnimation alphaAnimation = new AlphaAnimation(0.9f, 0.2f);
alphaAnimation.setRepeatCount(Animation.INFINITE);
alphaAnimation.setRepeatMode(Animation.REVERSE);

RotateAnimation rotateAnimation = new RotateAnimation(0, 360, 45, 45);
rotateAnimation.setRepeatCount(Animation.INFINITE);
rotateAnimation.setRepeatMode(Animation.RESTART);

AnimationSet animationSet = new AnimationSet(false);

animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(new ScaleAnimation(0.1f, 1, 0.1f, 1));
animationSet.addAnimation(new TranslateAnimation(50, 0, 150, 0));

animationSet.setDuration(3000);
iconView.startAnimation(animationSet);

Vous pouvez définir plusieurs animations pour que cela soit un peu compliqué en écrivant. (L'animation de propriété est meilleure ...)

Ce serait bien si je pouvais faire ça, Enfin, essayez d'augmenter l'échelle de tout l'onglet sélectionné. Je pense que vous devriez ajouter ce qui suit à onTabSelected et onTabUnselected respectivement.

final View view = viewGroup.getChildAt(tabLayout.getSelectedTabPosition());
view.setScaleX(1.25F);
view.setScaleY(1.25F);
final View view = viewGroup.getChildAt(tabLayout.getSelectedTabPosition());
view.setScaleX(1.0F);
view.setScaleY(1.0F);

Après cela, si vous en faites une méthode et que vous l'organisez dans l'instruction switch, elle est presque terminée comme vous le souhaitiez. Je vous remercie pour votre travail acharné.

finalement

... je ne veux plus construire avec Gradle et je veux utiliser Flutter

La source https://github.com/udzuv/AnimatingTabLayout

fin

Recommended Posts

Personnaliser les onglets avec une animation
Personnaliser la vue avec le modificateur de vue dans l'interface utilisateur Swift