I implemented TabLayout that animates like this.
!Caution! --The author of this article is a beginner in both Android and Java. Includes typographical errors, omissions, and mistakes. Please note. ――Since it was necessary to study Android-related matters, this is a summary and memorandum article. See others for technical details.
TabLayout + ViewPager
Create a layout file for the main screen with TabLayout + ViewPager. For details on how to use TabLayout and ViewPager, refer to other articles and officials.
https://qiita.com/furu8ma/items/1602a4bbed4303fec5b1
Here, simply place TabLayout and ViewPager and control them with MainActivity. As a bonus, I installed the title bar at the top.
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>
Make an Adapter and link it.
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);
Adapter settings
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; }
}
Since the tab title is set by Activity, getPageTitle () should return null. Set getItem () and getCount () respectively.
Next, set the text and icon in the contents of TabLayout.
// create TAB1
tabLayout.getTabAt(0).setCustomView(R.layout.item_tab1);
// create TAB2
tabLayout.getTabAt(1).setCustomView(R.layout.item_tab2);
:
:
Or
// 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);
:
:
It's easiest to set it in tabLayout like this I have to make a lot of layout files, If you setText () and setIcon (), you will not be able to handle it from the layout file, so ...
This time, inflate the layout file and bind the image and text with DataBinding. After that, we will set the View bound to the array of 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);
:
:
It's a hassle, but I feel that it has some great expandability. You can prepare a layout file for each tab,
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);
:
:
Get an instance of the child View for each tab You can set the animation for each part inside the tab. You can do it whether you use it or not.
I tried to summarize it like this.
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)));
}
Set tabLength = 4 and create about 4 tabs. It is easy to see if you make the DataBinding part a method and take the resource file you want to bind to the argument.
Next, we need a tab layout file, a model of DataBinding, so add it. See others for Data Binding Recommended
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;
}
}
Don't forget to add it to build.gradle
build.gradle
dataBinding {
enabled = true
}
At this point, tab generation is complete.
Next, I would like to set the animation. And before that
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);
}
Get the View you want to animate from the id of the child View for each tab as an array. Declare tabLayout and viewGroup as member variables so that they can be accessed from within the activity.
Then, from the listener settings
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) {
}
});
It seems best to use addOnTabSelectedListener. * Version 26.1.0 or later You can now extend TabLayout.OnTabSelectedListener. Now let's add an animation to each callback.
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) {
}
});
I think it would be nice to start the animation for the View acquired when each tab is selected and stop it when the selected state ends. First, let's start with the layout file. Create an anim folder under the res folder and create it in it. Implement a simple one using View Animation. I made it as a sample like this. See others for animation Recommended
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>
If you want to handle from the activity
// 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);
You can set multiple animations to make it look a little complicated by writing. (Property Animation is better ...)
It would be nice if I could do this, Finally, try to increase the scale of the entire selected tab. I think you should add the following to onTabSelected and onTabUnselected respectively.
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);
After that, if you make it into a method and arrange it in a switch statement, it is almost complete as you wanted to do. Thank you for your hard work.
... I don't want to build with Gradle anymore and I want to use Flutter
Source https://github.com/udzuv/AnimatingTabLayout
end