summaryrefslogtreecommitdiff
path: root/app/src/main/java/de/danoeh/antennapod
diff options
context:
space:
mode:
authorH. Lehmann <ByteHamster@users.noreply.github.com>2020-05-01 12:43:08 +0200
committerGitHub <noreply@github.com>2020-05-01 12:43:08 +0200
commitd6d8ec43e1d061dbe04d98f3d53625dda75762e1 (patch)
tree5919f55a24287c5b3cd3dcbf96d56d295a9f25bf /app/src/main/java/de/danoeh/antennapod
parent6aa4a9c091196db15a019c24f090ccc1986f91a1 (diff)
parentb870c233eed3e2ea085d41daf4c099f20b9794d4 (diff)
downloadAntennaPod-d6d8ec43e1d061dbe04d98f3d53625dda75762e1.zip
Merge branch 'develop' into develop
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod')
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java45
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java88
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java76
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java45
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java69
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java64
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java111
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/PagerIndicatorView.java28
12 files changed, 334 insertions, 212 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
index 7e052b445..9198c7a3e 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
@@ -410,7 +410,8 @@ public class EpisodesApplyActionFragment extends Fragment {
}
ActivityCompat.invalidateOptionsMenu(EpisodesApplyActionFragment.this.getActivity());
showSpeedDialIfAnyChecked();
- toolbar.setTitle(getString(R.string.num_selected_label, checkedIds.size()));
+ toolbar.setTitle(getResources().getQuantityString(R.plurals.num_selected_label,
+ checkedIds.size(), checkedIds.size()));
}
private void queueChecked() {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java
index 7f0326019..e905ccd95 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java
@@ -13,20 +13,28 @@ import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;
+
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.FragmentPagerAdapter;
-import androidx.viewpager.widget.ViewPager;
+import androidx.viewpager2.adapter.FragmentStateAdapter;
+import androidx.viewpager2.widget.ViewPager2;
+
import com.google.android.material.bottomsheet.BottomSheetBehavior;
+
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.text.DecimalFormat;
+
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.CastEnabledActivity;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.event.FavoritesEvent;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
-import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils;
@@ -50,12 +58,6 @@ import io.reactivex.Maybe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
-
-import java.text.DecimalFormat;
-import java.util.List;
/**
* Shows the audio player.
@@ -73,7 +75,7 @@ public class AudioPlayerFragment extends Fragment implements
PlaybackSpeedIndicatorView butPlaybackSpeed;
TextView txtvPlaybackSpeed;
- private ViewPager pager;
+ private ViewPager2 pager;
private PagerIndicatorView pageIndicator;
private TextView txtvPosition;
private TextView txtvLength;
@@ -127,11 +129,10 @@ public class AudioPlayerFragment extends Fragment implements
sbPosition.setOnSeekBarChangeListener(this);
pager = root.findViewById(R.id.pager);
- AudioPlayerPagerAdapter pagerAdapter = new AudioPlayerPagerAdapter(getChildFragmentManager());
- pager.setAdapter(pagerAdapter);
+ pager.setAdapter(new AudioPlayerPagerAdapter(this));
// Required for getChildAt(int) in ViewPagerBottomSheetBehavior to return the correct page
- pager.setOffscreenPageLimit(NUM_CONTENT_FRAGMENTS);
- pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
+ pager.setOffscreenPageLimit((int) NUM_CONTENT_FRAGMENTS);
+ pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
pager.post(() -> ((MainActivity) getActivity()).getBottomSheet().updateScrollingChild());
@@ -502,30 +503,30 @@ public class AudioPlayerFragment extends Fragment implements
return false;
}
- private static class AudioPlayerPagerAdapter extends FragmentPagerAdapter {
+ private static class AudioPlayerPagerAdapter extends FragmentStateAdapter {
private static final String TAG = "AudioPlayerPagerAdapter";
- public AudioPlayerPagerAdapter(FragmentManager fm) {
- super(fm);
+ public AudioPlayerPagerAdapter(@NonNull Fragment fragment) {
+ super(fragment);
}
+ @NonNull
@Override
- public Fragment getItem(int position) {
+ public Fragment createFragment(int position) {
Log.d(TAG, "getItem(" + position + ")");
switch (position) {
case POS_COVER:
return new CoverFragment();
case POS_DESCR:
return new ItemDescriptionFragment();
+ default:
case POS_CHAPTERS:
return new ChaptersFragment();
- default:
- return null;
}
}
@Override
- public int getCount() {
+ public int getItemCount() {
return NUM_CONTENT_FRAGMENTS;
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
index a3c07721a..6629d74e2 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
@@ -86,11 +86,16 @@ public class CompletedDownloadsFragment extends Fragment {
@Override
public void onStart() {
super.onStart();
- setHasOptionsMenu(true);
loadItems();
}
@Override
+ public void onResume() {
+ super.onResume();
+ setHasOptionsMenu(true);
+ }
+
+ @Override
public void onStop() {
super.onStop();
if (disposable != null) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
index 0305a7d48..a2fea9f24 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
@@ -51,6 +51,12 @@ public class DownloadLogFragment extends ListFragment {
}
@Override
+ public void onResume() {
+ super.onResume();
+ setHasOptionsMenu(true);
+ }
+
+ @Override
public void onStop() {
super.onStop();
if (disposable != null) {
@@ -61,8 +67,6 @@ public class DownloadLogFragment extends ListFragment {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- setHasOptionsMenu(true);
-
// add padding
final ListView lv = getListView();
lv.setClipToPadding(false);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java
index 6f537be96..cf0c6db90 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java
@@ -2,19 +2,21 @@ package de.danoeh.antennapod.fragment;
import android.content.Context;
import android.content.SharedPreferences;
-import android.content.res.Resources;
import android.os.Bundle;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
-import com.google.android.material.tabs.TabLayout;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.FragmentPagerAdapter;
-import androidx.viewpager.widget.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.fragment.app.Fragment;
+import androidx.viewpager2.adapter.FragmentStateAdapter;
+import androidx.viewpager2.widget.ViewPager2;
+
+import com.google.android.material.tabs.TabLayout;
+import com.google.android.material.tabs.TabLayoutMediator;
+
import de.danoeh.antennapod.R;
/**
@@ -29,10 +31,11 @@ public class DownloadsFragment extends Fragment {
public static final int POS_RUNNING = 0;
private static final int POS_COMPLETED = 1;
public static final int POS_LOG = 2;
+ private static final int TOTAL_COUNT = 3;
private static final String PREF_LAST_TAB_POSITION = "tab_position";
- private ViewPager viewPager;
+ private ViewPager2 viewPager;
private TabLayout tabLayout;
@Override
@@ -44,12 +47,30 @@ public class DownloadsFragment extends Fragment {
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
viewPager = root.findViewById(R.id.viewpager);
- DownloadsPagerAdapter pagerAdapter = new DownloadsPagerAdapter(getChildFragmentManager(), getResources());
- viewPager.setAdapter(pagerAdapter);
+ viewPager.setAdapter(new DownloadsPagerAdapter(this));
// Give the TabLayout the ViewPager
tabLayout = root.findViewById(R.id.sliding_tabs);
- tabLayout.setupWithViewPager(viewPager);
+ new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
+ switch (position) {
+ case POS_RUNNING:
+ tab.setText(R.string.downloads_running_label);
+ break;
+ case POS_COMPLETED:
+ tab.setText(R.string.downloads_completed_label);
+ break;
+ case POS_LOG:
+ tab.setText(R.string.downloads_log_label);
+ break;
+ default:
+ break;
+ }
+ }).attach();
+
+ // restore our last position
+ SharedPreferences prefs = getActivity().getSharedPreferences(TAG, Context.MODE_PRIVATE);
+ int lastPosition = prefs.getInt(PREF_LAST_TAB_POSITION, 0);
+ viewPager.setCurrentItem(lastPosition, false);
return root;
}
@@ -73,56 +94,29 @@ public class DownloadsFragment extends Fragment {
editor.apply();
}
- @Override
- public void onStart() {
- super.onStart();
-
- // restore our last position
- SharedPreferences prefs = getActivity().getSharedPreferences(TAG, Context.MODE_PRIVATE);
- int lastPosition = prefs.getInt(PREF_LAST_TAB_POSITION, 0);
- viewPager.setCurrentItem(lastPosition);
- }
-
- public static class DownloadsPagerAdapter extends FragmentPagerAdapter {
-
- final Resources resources;
+ public static class DownloadsPagerAdapter extends FragmentStateAdapter {
- public DownloadsPagerAdapter(FragmentManager fm, Resources resources) {
- super(fm);
- this.resources = resources;
+ DownloadsPagerAdapter(@NonNull Fragment fragment) {
+ super(fragment);
}
+ @NonNull
@Override
- public Fragment getItem(int position) {
+ public Fragment createFragment(int position) {
switch (position) {
case POS_RUNNING:
return new RunningDownloadsFragment();
case POS_COMPLETED:
return new CompletedDownloadsFragment();
+ default:
case POS_LOG:
return new DownloadLogFragment();
- default:
- return null;
}
}
@Override
- public int getCount() {
- return 3;
- }
-
- @Override
- public CharSequence getPageTitle(int position) {
- switch (position) {
- case POS_RUNNING:
- return resources.getString(R.string.downloads_running_label);
- case POS_COMPLETED:
- return resources.getString(R.string.downloads_completed_label);
- case POS_LOG:
- return resources.getString(R.string.downloads_log_label);
- default:
- return super.getPageTitle(position);
- }
+ public int getItemCount() {
+ return TOTAL_COUNT;
}
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java
index 275496f24..e98890627 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java
@@ -6,13 +6,17 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentPagerAdapter;
-import androidx.viewpager.widget.ViewPager;
+import androidx.viewpager2.adapter.FragmentStateAdapter;
+import androidx.viewpager2.widget.ViewPager2;
+
import com.google.android.material.tabs.TabLayout;
+import com.google.android.material.tabs.TabLayoutMediator;
+
import de.danoeh.antennapod.R;
public class EpisodesFragment extends Fragment {
@@ -27,7 +31,7 @@ public class EpisodesFragment extends Fragment {
private TabLayout tabLayout;
- private ViewPager viewPager;
+ private ViewPager2 viewPager;
//Mandatory Constructor
public EpisodesFragment() {
@@ -46,11 +50,32 @@ public class EpisodesFragment extends Fragment {
toolbar.setTitle(R.string.episodes_label);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
viewPager = rootView.findViewById(R.id.viewpager);
- viewPager.setAdapter(new EpisodesPagerAdapter());
+ viewPager.setAdapter(new EpisodesPagerAdapter(this));
// Give the TabLayout the ViewPager
tabLayout = rootView.findViewById(R.id.sliding_tabs);
- tabLayout.setupWithViewPager(viewPager);
+
+ new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
+ switch (position) {
+ case POS_NEW_EPISODES:
+ tab.setText(R.string.new_episodes_label);
+ break;
+ case POS_ALL_EPISODES:
+ tab.setText(R.string.all_episodes_short_label);
+ break;
+ case POS_FAV_EPISODES:
+ tab.setText(R.string.favorite_episodes_label);
+ break;
+ default:
+ break;
+ }
+ }).attach();
+
+ // restore our last position
+ SharedPreferences prefs = getActivity().getSharedPreferences(TAG, Context.MODE_PRIVATE);
+ int lastPosition = prefs.getInt(PREF_LAST_TAB_POSITION, 0);
+ viewPager.setCurrentItem(lastPosition, false);
+
return rootView;
}
@@ -64,52 +89,29 @@ public class EpisodesFragment extends Fragment {
editor.apply();
}
- @Override
- public void onStart() {
- super.onStart();
-
- // restore our last position
- SharedPreferences prefs = getActivity().getSharedPreferences(TAG, Context.MODE_PRIVATE);
- int lastPosition = prefs.getInt(PREF_LAST_TAB_POSITION, 0);
- viewPager.setCurrentItem(lastPosition);
- }
-
- public class EpisodesPagerAdapter extends FragmentPagerAdapter {
+ static class EpisodesPagerAdapter extends FragmentStateAdapter {
- public EpisodesPagerAdapter() {
- super(getChildFragmentManager());
+ EpisodesPagerAdapter(@NonNull Fragment fragment) {
+ super(fragment);
}
- @Override
@NonNull
- public Fragment getItem(int position) {
+ @Override
+ public Fragment createFragment(int position) {
switch (position) {
- case 0:
+ case POS_NEW_EPISODES:
return new NewEpisodesFragment();
- case 1:
+ case POS_ALL_EPISODES:
return new AllEpisodesFragment();
default:
+ case POS_FAV_EPISODES:
return new FavoriteEpisodesFragment();
}
}
@Override
- public int getCount() {
+ public int getItemCount() {
return TOTAL_COUNT;
}
-
- @Override
- public CharSequence getPageTitle(int position) {
- switch (position) {
- case POS_ALL_EPISODES:
- return getString(R.string.all_episodes_short_label);
- case POS_NEW_EPISODES:
- return getString(R.string.new_episodes_label);
- case POS_FAV_EPISODES:
- return getString(R.string.favorite_episodes_label);
- default:
- return super.getPageTitle(position);
- }
- }
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
index 189e026a1..4f283a9ab 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
@@ -83,7 +83,6 @@ public abstract class EpisodesListFragment extends Fragment {
@Override
public void onStart() {
super.onStart();
- setHasOptionsMenu(true);
EventBus.getDefault().register(this);
loadItems();
}
@@ -91,6 +90,7 @@ public abstract class EpisodesListFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
+ setHasOptionsMenu(true);
registerForContextMenu(recyclerView);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java
index aac89a65f..0c7eb23d2 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java
@@ -7,29 +7,30 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentStatePagerAdapter;
-import androidx.viewpager.widget.ViewPager;
+import androidx.viewpager2.adapter.FragmentStateAdapter;
+import androidx.viewpager2.widget.ViewPager2;
+
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.CastEnabledActivity;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.storage.DBReader;
-import de.danoeh.antennapod.core.util.Flavors;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
/**
* Displays information about a list of FeedItems.
@@ -41,7 +42,7 @@ public class ItemPagerFragment extends Fragment {
/**
* Creates a new instance of an ItemPagerFragment.
*
- * @param feeditems The IDs of the FeedItems that belong to the same list
+ * @param feeditems The IDs of the FeedItems that belong to the same list
* @param feedItemPos The position of the FeedItem that is currently shown
* @return The ItemFragment instance
*/
@@ -76,31 +77,21 @@ public class ItemPagerFragment extends Fragment {
feedItems = getArguments().getLongArray(ARG_FEEDITEMS);
int feedItemPos = getArguments().getInt(ARG_FEEDITEM_POS);
- ViewPager pager = layout.findViewById(R.id.pager);
+ ViewPager2 pager = layout.findViewById(R.id.pager);
// FragmentStatePagerAdapter documentation:
// > When using FragmentStatePagerAdapter the host ViewPager must have a valid ID set.
// When opening multiple ItemPagerFragments by clicking "item" -> "visit podcast" -> "item" -> etc,
// the ID is no longer unique and FragmentStatePagerAdapter does not display any pages.
int newId = ViewCompat.generateViewId();
pager.setId(newId);
- pager.setAdapter(new ItemPagerAdapter());
- pager.setCurrentItem(feedItemPos);
+ pager.setAdapter(new ItemPagerAdapter(this));
+ pager.setCurrentItem(feedItemPos, false);
loadItem(feedItems[feedItemPos]);
- pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
-
- }
-
+ pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
loadItem(feedItems[position]);
}
-
- @Override
- public void onPageScrollStateChanged(int state) {
-
- }
});
EventBus.getDefault().register(this);
@@ -173,20 +164,20 @@ public class ItemPagerFragment extends Fragment {
((MainActivity) getActivity()).loadChildFragment(fragment);
}
- private class ItemPagerAdapter extends FragmentStatePagerAdapter {
+ private class ItemPagerAdapter extends FragmentStateAdapter {
- ItemPagerAdapter() {
- super(getFragmentManager(), BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
+ ItemPagerAdapter(@NonNull Fragment fragment) {
+ super(fragment);
}
@NonNull
@Override
- public Fragment getItem(int position) {
+ public Fragment createFragment(int position) {
return ItemFragment.newInstance(feedItems[position]);
}
@Override
- public int getCount() {
+ public int getItemCount() {
return feedItems.length;
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java
index 3ebdd80d8..4ccc53118 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java
@@ -4,13 +4,17 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.FragmentPagerAdapter;
-import androidx.viewpager.widget.ViewPager;
+import androidx.viewpager2.adapter.FragmentStateAdapter;
+import androidx.viewpager2.widget.ViewPager2;
+
import com.google.android.material.tabs.TabLayout;
+import com.google.android.material.tabs.TabLayoutMediator;
+
import de.danoeh.antennapod.R;
/**
@@ -18,6 +22,11 @@ import de.danoeh.antennapod.R;
*/
public class GpodnetMainFragment extends Fragment {
+ private static final int NUM_PAGES = 2;
+ private static final int POS_TOPLIST = 0;
+ private static final int POS_TAGS = 1;
+ private static final int POS_SUGGESTIONS = 2;
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
@@ -26,63 +35,59 @@ public class GpodnetMainFragment extends Fragment {
toolbar.setTitle(R.string.gpodnet_main_label);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
- ViewPager viewPager = root.findViewById(R.id.viewpager);
- GpodnetPagerAdapter pagerAdapter = new GpodnetPagerAdapter(getChildFragmentManager());
+ ViewPager2 viewPager = root.findViewById(R.id.viewpager);
+ GpodnetPagerAdapter pagerAdapter = new GpodnetPagerAdapter(this);
viewPager.setAdapter(pagerAdapter);
// Give the TabLayout the ViewPager
TabLayout tabLayout = root.findViewById(R.id.sliding_tabs);
- tabLayout.setupWithViewPager(viewPager);
+
+ new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
+ switch (position) {
+ case POS_TAGS:
+ tab.setText(R.string.gpodnet_taglist_header);
+ break;
+ case POS_TOPLIST:
+ tab.setText(R.string.gpodnet_toplist_header);
+ break;
+ default:
+ case POS_SUGGESTIONS:
+ tab.setText(R.string.gpodnet_suggestions_header);
+ break;
+ }
+ }).attach();
return root;
}
- public class GpodnetPagerAdapter extends FragmentPagerAdapter {
- private static final int NUM_PAGES = 2;
- private static final int POS_TOPLIST = 0;
- private static final int POS_TAGS = 1;
- private static final int POS_SUGGESTIONS = 2;
+ public static class GpodnetPagerAdapter extends FragmentStateAdapter {
- public GpodnetPagerAdapter(FragmentManager fm) {
- super(fm);
+ GpodnetPagerAdapter(@NonNull Fragment fragment) {
+ super(fragment);
}
+ @NonNull
@Override
- public Fragment getItem(int i) {
+ public Fragment createFragment(int position) {
Bundle arguments = new Bundle();
arguments.putBoolean(PodcastListFragment.ARGUMENT_HIDE_TOOLBAR, true);
- switch (i) {
+ switch (position) {
case POS_TAGS:
return new TagListFragment();
case POS_TOPLIST:
PodcastListFragment topListFragment = new PodcastTopListFragment();
topListFragment.setArguments(arguments);
return topListFragment;
+ default:
case POS_SUGGESTIONS:
PodcastListFragment suggestionsFragment = new SuggestionListFragment();
suggestionsFragment.setArguments(arguments);
return suggestionsFragment;
- default:
- return null;
- }
- }
-
- @Override
- public CharSequence getPageTitle(int position) {
- switch (position) {
- case POS_TAGS:
- return getString(R.string.gpodnet_taglist_header);
- case POS_TOPLIST:
- return getString(R.string.gpodnet_toplist_header);
- case POS_SUGGESTIONS:
- return getString(R.string.gpodnet_suggestions_header);
- default:
- return super.getPageTitle(position);
}
}
@Override
- public int getCount() {
+ public int getItemCount() {
return NUM_PAGES;
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java
index 4b8cf1e1c..b455a10ee 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java
@@ -1,17 +1,17 @@
package de.danoeh.antennapod.fragment.preferences;
-import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.FragmentPagerAdapter;
-import androidx.viewpager.widget.ViewPager;
+import androidx.viewpager2.adapter.FragmentStateAdapter;
+import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
+import com.google.android.material.tabs.TabLayoutMediator;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.PreferenceActivity;
@@ -29,25 +29,35 @@ public class StatisticsFragment extends Fragment {
private TabLayout tabLayout;
- private ViewPager viewPager;
+ private ViewPager2 viewPager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.pager_fragment, container, false);
viewPager = rootView.findViewById(R.id.viewpager);
- viewPager.setAdapter(new StatisticsPagerAdapter(getChildFragmentManager(), getResources()));
-
+ viewPager.setAdapter(new StatisticsPagerAdapter(this));
// Give the TabLayout the ViewPager
tabLayout = rootView.findViewById(R.id.sliding_tabs);
- tabLayout.setupWithViewPager(viewPager);
+ new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
+ switch (position) {
+ case POS_LISTENED_HOURS:
+ tab.setText(R.string.playback_statistics_label);
+ break;
+ case POS_SPACE_TAKEN:
+ tab.setText(R.string.download_statistics_label);
+ break;
+ default:
+ break;
+ }
+ }).attach();
rootView.findViewById(R.id.toolbar).setVisibility(View.GONE);
@@ -60,39 +70,27 @@ public class StatisticsFragment extends Fragment {
((PreferenceActivity) getActivity()).getSupportActionBar().setTitle(R.string.statistics_label);
}
- public static class StatisticsPagerAdapter extends FragmentPagerAdapter {
-
- private final Resources resources;
+ public static class StatisticsPagerAdapter extends FragmentStateAdapter {
- public StatisticsPagerAdapter(FragmentManager fm, Resources resources) {
- super(fm);
- this.resources = resources;
+ StatisticsPagerAdapter(@NonNull Fragment fragment) {
+ super(fragment);
}
+ @NonNull
@Override
- public Fragment getItem(int position) {
- if (position == 0) {
- return new PlaybackStatisticsFragment();
- } else {
- return new DownloadStatisticsFragment();
+ public Fragment createFragment(int position) {
+ switch (position) {
+ case POS_LISTENED_HOURS:
+ return new PlaybackStatisticsFragment();
+ default:
+ case POS_SPACE_TAKEN:
+ return new DownloadStatisticsFragment();
}
}
@Override
- public int getCount() {
+ public int getItemCount() {
return TOTAL_COUNT;
}
-
- @Override
- public CharSequence getPageTitle(int position) {
- switch (position) {
- case POS_LISTENED_HOURS:
- return resources.getString(R.string.playback_statistics_label);
- case POS_SPACE_TAKEN:
- return resources.getString(R.string.download_statistics_label);
- default:
- return super.getPageTitle(position);
- }
- }
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java b/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java
new file mode 100644
index 000000000..a4daa9109
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Source: https://github.com/android/views-widgets-samples/blob/87e58d1/ViewPager2/app/src/main/java/androidx/viewpager2/integration/testapp/NestedScrollableHost.kt
+ * And modified for our need
+ */
+
+package de.danoeh.antennapod.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewParent;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.viewpager2.widget.ViewPager2;
+
+import static androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL;
+import static androidx.viewpager2.widget.ViewPager2.ORIENTATION_VERTICAL;
+
+/**
+ * Layout to wrap a scrollable component inside a ViewPager2. Provided as a solution to the problem
+ * where pages of ViewPager2 have nested scrollable elements that scroll in the same direction as
+ * ViewPager2. The scrollable element needs to be the immediate and only child of this host layout.
+ *
+ * <p>This solution has limitations when using multiple levels of nested scrollable elements
+ * (e.g. a horizontal RecyclerView in a vertical RecyclerView in a horizontal ViewPager2).
+ */
+class NestedScrollableHost extends FrameLayout {
+
+ public NestedScrollableHost(@NonNull Context context) {
+ super(context);
+ touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ }
+
+ public NestedScrollableHost(@NonNull Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ }
+
+ private int touchSlop = 0;
+ private float initialX = 0f;
+ private float initialY = 0f;
+
+ private ViewPager2 getParentViewPager() {
+ View v = (View) getParent();
+ while (v != null && !(v instanceof ViewPager2)) {
+ v = (View) v.getParent();
+ }
+ return v == null ? null : (ViewPager2) v;
+ }
+
+ public boolean onInterceptTouchEvent(MotionEvent e) {
+ ViewPager2 parentViewPager = getParentViewPager();
+ if (parentViewPager == null) {
+ return super.onInterceptTouchEvent(e);
+ }
+
+ ViewParent parent = getParent();
+ int orientation = parentViewPager.getOrientation();
+
+ if (e.getAction() == MotionEvent.ACTION_DOWN) {
+ initialX = e.getX();
+ initialY = e.getY();
+ parent.requestDisallowInterceptTouchEvent(true);
+ } else if (e.getAction() == MotionEvent.ACTION_MOVE) {
+ int dx = (int) (e.getX() - initialX);
+ int dy = (int) (e.getY() - initialY);
+ boolean isVpHorizontal = orientation == ORIENTATION_HORIZONTAL;
+
+ // assuming ViewPager2 touch-slop is 2x touch-slop of child
+ float scaledDx = Math.abs(dx) * (isVpHorizontal ? .5f : 1f);
+ float scaledDy = Math.abs(dy) * (isVpHorizontal ? 1f : .5f);
+ if (scaledDx > touchSlop || scaledDy > touchSlop) {
+ int value = isVpHorizontal ? dy : dx;
+ if (isVpHorizontal == (scaledDy > scaledDx)) {
+ // Gesture is perpendicular
+ orientation = orientation == ORIENTATION_VERTICAL
+ ? ORIENTATION_HORIZONTAL : ORIENTATION_VERTICAL;
+ value = isVpHorizontal ? dy : dx;
+ }
+
+ int direction = (int) -Math.copySign(1, value);
+ View child = getChildAt(0);
+ if (orientation == ORIENTATION_HORIZONTAL) {
+ parent.requestDisallowInterceptTouchEvent(child.canScrollHorizontally(direction));
+ } else {
+ parent.requestDisallowInterceptTouchEvent(child.canScrollVertically(direction));
+ }
+ }
+ }
+
+ return super.onInterceptTouchEvent(e);
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/PagerIndicatorView.java b/app/src/main/java/de/danoeh/antennapod/view/PagerIndicatorView.java
index 53a95eede..240a565c8 100644
--- a/app/src/main/java/de/danoeh/antennapod/view/PagerIndicatorView.java
+++ b/app/src/main/java/de/danoeh/antennapod/view/PagerIndicatorView.java
@@ -1,15 +1,20 @@
package de.danoeh.antennapod.view;
+import android.animation.ArgbEvaluator;
import android.content.Context;
import android.content.res.TypedArray;
-import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
+
import androidx.annotation.Nullable;
-import androidx.vectordrawable.graphics.drawable.ArgbEvaluator;
-import androidx.viewpager.widget.ViewPager;
+import androidx.core.text.TextUtilsCompat;
+import androidx.core.view.ViewCompat;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.viewpager2.widget.ViewPager2;
+
+import java.util.Locale;
public class PagerIndicatorView extends View {
private final Paint paint = new Paint();
@@ -38,26 +43,31 @@ public class PagerIndicatorView extends View {
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
- int[] colorAttrs = new int[] { android.R.attr.textColorSecondary };
+ int[] colorAttrs = new int[]{android.R.attr.textColorSecondary};
TypedArray a = getContext().obtainStyledAttributes(colorAttrs);
circleColorHighlight = a.getColor(0, 0xffffffff);
circleColor = (Integer) new ArgbEvaluator().evaluate(0.8f, 0x00ffffff, circleColorHighlight);
a.recycle();
}
- public void setViewPager(ViewPager pager) {
- numPages = pager.getAdapter().getCount();
- pager.getAdapter().registerDataSetObserver(new DataSetObserver() {
+ public void setViewPager(ViewPager2 pager) {
+ numPages = pager.getAdapter().getItemCount();
+ pager.getAdapter().registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
- numPages = pager.getAdapter().getCount();
+ numPages = pager.getAdapter().getItemCount();
invalidate();
}
});
- pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
+ boolean isLocaleRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault())
+ == ViewCompat.LAYOUT_DIRECTION_RTL;
+ pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
PagerIndicatorView.this.position = position + positionOffset;
+ if (isLocaleRtl) {
+ PagerIndicatorView.this.position = numPages - 1 - PagerIndicatorView.this.position;
+ }
invalidate();
}
});