Foggy day
Android(Java, kotlin) - Appbar Animation with ViewPager inside Fragment 본문
Android(Java, kotlin) - Appbar Animation with ViewPager inside Fragment
jinhan38 2020. 12. 29. 01:03
When making app, we mostly use viewpager and tablayout, and appbar. Animation showing or hiding appbar in activity is not too difficult. But, Sometimes a slightly complicated UI bothers us. For example, there is a fragment A in the activity, and the AppBar, tablayout, and ViewPager ars in the A fragment. The VewPapger has fragments B, C, and D. In this structure what i want to do is an animation that shows and hides fragment B's appBar when scrolling up and down fragments B and C, not D. Of coures, the viewpager swipe functions show also work.
This arcticle is a sample that implements the above example.
If you know about databinding, appbar, viewpager, and tablayout, it will help you understand this article. It does not describe in detail the databinding, appbar, viewpager, and tablaout.
Video preview
Let's get started.
First of all, I will show you the package structure. I used the following classes.
1. activity_app_bar_hide_animation.xml
Here, there is only the framelayout that will be the container of the fragment.
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
2. AppBarHideAnimationActivity
Hide actionbar and commit the fragment to be created next.
※ It you have a nestedScrollview in this layout, Appbar show/hide function will be not working.
public class AppBarHideAnimationActivity extends AppCompatActivity {
private ActivityAppBarHideAnimationBinding binding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
binding = ActivityAppBarHideAnimationBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
Fragment fragment = new AppBarHideAnimationFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragmentContainer, fragment);
fragmentTransaction.commit();
}
}
3. app_bar_hide_animation_fragment.xml
Here, there are appbarlayout, viewpager2 and tablayout. The remarkable part is that CoordinatorLayout cover the whole. For appbar behavior, it is absolutely necessary. Also, Don;t forget the code below.
- app:layout_scrollFlags="scroll|enterAlways|snap"
- app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways|snap">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="It is Toolbar"
android:textColor="@color/white"
android:textSize="17dp" />
</androidx.appcompat.widget.Toolbar>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@color/white"
app:tabIndicatorColor="#9C27B0"
app:tabIndicatorHeight="5dp"
app:tabMode="fixed"
app:tabRippleColor="@android:color/transparent"
app:tabSelectedTextColor="#9C27B0">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="First" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Second" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Third" />
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>
4. ViewPagerAdapter
Depending on type of viewpager, the way how to create viewpagerAdapter is different.
In this article, I used this.
public class ViewPagerAdapter extends FragmentStateAdapter {
private String[] dataList;
public ViewPagerAdapter(@NonNull FragmentActivity fragmentActivity, String[] dataList) {
super(fragmentActivity);
this.dataList = dataList;
}
@NonNull
@Override
public Fragment createFragment(int position) {
Fragment fragment;
switch (position) {
case 0:
fragment = new FirstFragment();
break;
case 1:
fragment = new SecondFragment();
break;
case 2:
fragment = new ThirdFragment();
break;
default:
throw new IllegalStateException("Unexpected value: " + position);
}
return fragment;
}
@Override
public int getItemCount() {
return dataList.length;
}
}
5. AppBarHideAnimationFragment
Connect viewpager, viewpagerAdapter, and tablayout.
public class AppBarHideAnimationFragment extends Fragment {
private AppBarHideAnimationFragmentBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = AppBarHideAnimationFragmentBinding.inflate(getLayoutInflater());
String[] dataList = new String[]{"First", "Second", "Third"};
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getActivity(), dataList);
binding.viewPager.setAdapter(viewPagerAdapter); // note : It is ViewPager2, Not Viewpager
//This is from official google document.
//If you want know more about this, please refer to this link :
//https://developer.android.com/guide/navigation/navigation-swipe-view-2?hl=ko
new TabLayoutMediator(binding.tabLayout, binding.viewPager, ((tab, position) -> tab.setText("OBJECT " + (position + 1))
)).attach();
return binding.getRoot();
}
}
6. fragment_first.xml
This xml has NestedScrollview.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:background="@color/gray"
tools:context=".viewPager.depth.fragment.FirstFragment">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="Scroll Animation 1"
android:textColor="@color/white"
android:textSize="30dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="Scroll Animation 2"
android:textColor="@color/white"
android:textSize="30dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="Scroll Animation 3"
android:textColor="@color/white"
android:textSize="30dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="Scroll Animation 4"
android:textColor="@color/white"
android:textSize="30dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
class FirstFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_first, container, false)
}
}
7. fragment_second.xml
SecondFragment is the same as the FirstFragment.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:background="@color/purple_500"
tools:context=".viewPager.depth.fragment.SecondFragment">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="Scroll Animation 1"
android:textColor="@color/white"
android:textSize="30dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="Scroll Animation 2"
android:textColor="@color/white"
android:textSize="30dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="Scroll Animation 3"
android:textColor="@color/white"
android:textSize="30dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="Scroll Animation 4"
android:textColor="@color/white"
android:textSize="30dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</FrameLayout>
class SecondFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_second, container, false)
}
}
8. fragment_third.xml
ThridFragment only changed the background color. The Third doesn't have scrollview. So animation appbar isn't working
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:background="@color/teal_200"
tools:context=".viewPager.depth.fragment.ThirdFragment">
</FrameLayout>
class ThirdFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_third, container, false)
}
}
All the necessary work is done. It should work. you can toolbar visibility by scrolling OBJECT1, OBJECT2. But OBJECT3 not have scrollview, so can not controll toolbar visibility.
If you have any questions, please leave a comment.
'Android' 카테고리의 다른 글
Android - Viewpager2 inside Viewpager2 (0) | 2021.01.01 |
---|---|
Android(kotlin, java) - LayoutParams, Viewgroup to change margin, width, and height in code (0) | 2020.12.31 |
Android Custom View: Extending The Views (0) | 2020.12.27 |
Android(kotlin) - custom circle progressBar (0) | 2020.12.27 |
Android - 최고의 커스텀 뷰 가이드 (0) | 2020.12.27 |