mirror of
https://github.com/nextcloud/android.git
synced 2024-11-21 20:55:31 +03:00
Merge pull request #13093 from nextcloud/view-pager-2-implementation
Migrate to View Pager 2 & Crash-Fix | Farewell to ViewPager 1 🥳
This commit is contained in:
commit
5d83a2961b
12 changed files with 96 additions and 97 deletions
|
@ -18,7 +18,7 @@ import androidx.activity.OnBackPressedCallback
|
|||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.nextcloud.android.common.ui.theme.utils.ColorRole
|
||||
import com.nextcloud.client.account.UserAccountManager
|
||||
import com.nextcloud.client.appinfo.AppInfo
|
||||
|
@ -39,7 +39,7 @@ import javax.inject.Inject
|
|||
/**
|
||||
* Activity displaying general feature after a fresh install.
|
||||
*/
|
||||
class FirstRunActivity : BaseActivity(), ViewPager.OnPageChangeListener, Injectable {
|
||||
class FirstRunActivity : BaseActivity(), Injectable {
|
||||
|
||||
@JvmField
|
||||
@Inject
|
||||
|
@ -171,10 +171,14 @@ class FirstRunActivity : BaseActivity(), ViewPager.OnPageChangeListener, Injecta
|
|||
|
||||
@Suppress("SpreadOperator")
|
||||
private fun setupFeaturesViewAdapter() {
|
||||
val featuresViewAdapter = FeaturesViewAdapter(supportFragmentManager, *firstRun)
|
||||
binding.progressIndicator.setNumberOfSteps(featuresViewAdapter.count)
|
||||
val featuresViewAdapter = FeaturesViewAdapter(this, *firstRun)
|
||||
binding.progressIndicator.setNumberOfSteps(featuresViewAdapter.itemCount)
|
||||
binding.contentPanel.adapter = featuresViewAdapter
|
||||
binding.contentPanel.addOnPageChangeListener(this)
|
||||
binding.contentPanel.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
binding.progressIndicator.animateToStep(position + 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun handleOnBackPressed() {
|
||||
|
@ -236,18 +240,6 @@ class FirstRunActivity : BaseActivity(), ViewPager.OnPageChangeListener, Injecta
|
|||
super.onStop()
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
// unused but to be implemented due to abstract parent
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
binding.progressIndicator.animateToStep(position + 1)
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
// unused but to be implemented due to abstract parent
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val EXTRA_ALLOW_CLOSE = "ALLOW_CLOSE"
|
||||
const val EXTRA_EXIT = "EXIT"
|
||||
|
|
|
@ -13,7 +13,7 @@ import android.os.Bundle
|
|||
import android.view.View
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
||||
import com.nextcloud.android.common.ui.theme.utils.ColorRole
|
||||
import com.nextcloud.client.appinfo.AppInfo
|
||||
import com.nextcloud.client.di.Injectable
|
||||
|
@ -29,7 +29,7 @@ import javax.inject.Inject
|
|||
/**
|
||||
* Activity displaying new features after an update.
|
||||
*/
|
||||
class WhatsNewActivity : FragmentActivity(), ViewPager.OnPageChangeListener, Injectable {
|
||||
class WhatsNewActivity : FragmentActivity(), Injectable {
|
||||
|
||||
@JvmField
|
||||
@Inject
|
||||
|
@ -64,7 +64,11 @@ class WhatsNewActivity : FragmentActivity(), ViewPager.OnPageChangeListener, Inj
|
|||
val showWebView = urls.isNotEmpty()
|
||||
|
||||
setupFeatureViewAdapter(showWebView, urls)
|
||||
binding.contentPanel.addOnPageChangeListener(this)
|
||||
binding.contentPanel.registerOnPageChangeCallback(object : OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
controlPanelOnPageSelected(position)
|
||||
}
|
||||
})
|
||||
setupForwardImageButton()
|
||||
setupSkipImageButton()
|
||||
setupWelcomeText(showWebView)
|
||||
|
@ -75,15 +79,15 @@ class WhatsNewActivity : FragmentActivity(), ViewPager.OnPageChangeListener, Inj
|
|||
@Suppress("SpreadOperator")
|
||||
private fun setupFeatureViewAdapter(showWebView: Boolean, urls: Array<String>) {
|
||||
val adapter = if (showWebView) {
|
||||
FeaturesWebViewAdapter(supportFragmentManager, *urls)
|
||||
FeaturesWebViewAdapter(this, *urls)
|
||||
} else {
|
||||
onboarding?.let {
|
||||
FeaturesViewAdapter(supportFragmentManager, *it.whatsNew)
|
||||
FeaturesViewAdapter(this, *it.whatsNew)
|
||||
}
|
||||
}
|
||||
|
||||
adapter?.let {
|
||||
binding.progressIndicator.setNumberOfSteps(it.count)
|
||||
binding.progressIndicator.setNumberOfSteps(it.itemCount)
|
||||
binding.contentPanel.adapter = it
|
||||
}
|
||||
}
|
||||
|
@ -142,14 +146,8 @@ class WhatsNewActivity : FragmentActivity(), ViewPager.OnPageChangeListener, Inj
|
|||
preferences?.lastSeenVersionCode = BuildConfig.VERSION_CODE
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
private fun controlPanelOnPageSelected(position: Int) {
|
||||
binding.progressIndicator.animateToStep(position + 1)
|
||||
updateNextButtonIfNeeded()
|
||||
}
|
||||
|
||||
@Suppress("EmptyFunctionBlock")
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||
|
||||
@Suppress("EmptyFunctionBlock")
|
||||
override fun onPageScrollStateChanged(state: Int) {}
|
||||
}
|
||||
|
|
|
@ -9,26 +9,28 @@ package com.owncloud.android.ui.adapter;
|
|||
import com.owncloud.android.features.FeatureItem;
|
||||
import com.owncloud.android.ui.fragment.FeatureFragment;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
public class FeaturesViewAdapter extends FragmentPagerAdapter {
|
||||
public class FeaturesViewAdapter extends FragmentStateAdapter {
|
||||
|
||||
private FeatureItem[] mFeatures;
|
||||
private final FeatureItem[] mFeatures;
|
||||
|
||||
public FeaturesViewAdapter(FragmentManager fm, FeatureItem... features) {
|
||||
super(fm);
|
||||
public FeaturesViewAdapter(FragmentActivity fragmentActivity, FeatureItem... features) {
|
||||
super(fragmentActivity);
|
||||
mFeatures = features;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
public Fragment createFragment(int position) {
|
||||
return FeatureFragment.newInstance(mFeatures[position]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
public int getItemCount() {
|
||||
return mFeatures.length;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,25 +8,27 @@ package com.owncloud.android.ui.adapter;
|
|||
|
||||
import com.owncloud.android.ui.fragment.FeatureWebFragment;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
public class FeaturesWebViewAdapter extends FragmentPagerAdapter {
|
||||
public class FeaturesWebViewAdapter extends FragmentStateAdapter {
|
||||
private String[] mWebUrls;
|
||||
|
||||
public FeaturesWebViewAdapter(FragmentManager fm, String... webUrls) {
|
||||
super(fm);
|
||||
public FeaturesWebViewAdapter(FragmentActivity fragmentActivity, String... webUrls) {
|
||||
super(fragmentActivity);
|
||||
mWebUrls = webUrls;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
public Fragment createFragment(int position) {
|
||||
return FeatureWebFragment.newInstance(mWebUrls[position]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
public int getItemCount() {
|
||||
return mWebUrls.length;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,13 +15,13 @@ import com.owncloud.android.utils.MimeTypeUtil;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
/**
|
||||
* File details pager adapter.
|
||||
*/
|
||||
public class FileDetailTabAdapter extends FragmentStatePagerAdapter {
|
||||
public class FileDetailTabAdapter extends FragmentStateAdapter {
|
||||
private final OCFile file;
|
||||
private final User user;
|
||||
private final boolean showSharingTab;
|
||||
|
@ -30,33 +30,16 @@ public class FileDetailTabAdapter extends FragmentStatePagerAdapter {
|
|||
private FileDetailActivitiesFragment fileDetailActivitiesFragment;
|
||||
private ImageDetailFragment imageDetailFragment;
|
||||
|
||||
public FileDetailTabAdapter(FragmentManager fm,
|
||||
public FileDetailTabAdapter(FragmentActivity fragmentActivity,
|
||||
OCFile file,
|
||||
User user,
|
||||
boolean showSharingTab) {
|
||||
super(fm);
|
||||
super(fragmentActivity);
|
||||
this.file = file;
|
||||
this.user = user;
|
||||
this.showSharingTab = showSharingTab;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
default:
|
||||
fileDetailActivitiesFragment = FileDetailActivitiesFragment.newInstance(file, user);
|
||||
return fileDetailActivitiesFragment;
|
||||
case 1:
|
||||
fileDetailSharingFragment = FileDetailSharingFragment.newInstance(file, user);
|
||||
return fileDetailSharingFragment;
|
||||
case 2:
|
||||
imageDetailFragment = ImageDetailFragment.newInstance(file, user);
|
||||
return imageDetailFragment;
|
||||
}
|
||||
}
|
||||
|
||||
public FileDetailSharingFragment getFileDetailSharingFragment() {
|
||||
return fileDetailSharingFragment;
|
||||
}
|
||||
|
@ -69,8 +52,27 @@ public class FileDetailTabAdapter extends FragmentStatePagerAdapter {
|
|||
return imageDetailFragment;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public int getCount() {
|
||||
public Fragment createFragment(int position) {
|
||||
return switch (position) {
|
||||
default -> {
|
||||
fileDetailActivitiesFragment = FileDetailActivitiesFragment.newInstance(file, user);
|
||||
yield fileDetailActivitiesFragment;
|
||||
}
|
||||
case 1 -> {
|
||||
fileDetailSharingFragment = FileDetailSharingFragment.newInstance(file, user);
|
||||
yield fileDetailSharingFragment;
|
||||
}
|
||||
case 2 -> {
|
||||
imageDetailFragment = ImageDetailFragment.newInstance(file, user);
|
||||
yield imageDetailFragment;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
if (showSharingTab) {
|
||||
if (MimeTypeUtil.isImage(file)) {
|
||||
return 3;
|
||||
|
|
|
@ -75,6 +75,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.res.ResourcesCompat;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
/**
|
||||
* This Fragment is used to display the details about a file.
|
||||
|
@ -166,7 +167,12 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
|
|||
if (binding == null) {
|
||||
return null;
|
||||
}
|
||||
return ((FileDetailTabAdapter) binding.pager.getAdapter()).getFileDetailSharingFragment();
|
||||
|
||||
if (binding.pager.getAdapter() instanceof FileDetailTabAdapter adapter) {
|
||||
return adapter.getFileDetailSharingFragment();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,7 +181,11 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
|
|||
* @return reference to the {@link FileDetailActivitiesFragment}
|
||||
*/
|
||||
public FileDetailActivitiesFragment getFileDetailActivitiesFragment() {
|
||||
return ((FileDetailTabAdapter) binding.pager.getAdapter()).getFileDetailActivitiesFragment();
|
||||
if (binding.pager.getAdapter() instanceof FileDetailTabAdapter adapter) {
|
||||
return adapter.getFileDetailActivitiesFragment();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void goBackToOCFileListFragment() {
|
||||
|
@ -296,12 +306,13 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
|
|||
|
||||
viewThemeUtils.material.themeTabLayout(binding.tabLayout);
|
||||
|
||||
final FileDetailTabAdapter adapter = new FileDetailTabAdapter(getFragmentManager(),
|
||||
final FileDetailTabAdapter adapter = new FileDetailTabAdapter(requireActivity(),
|
||||
getFile(),
|
||||
user,
|
||||
showSharingTab());
|
||||
binding.pager.setAdapter(adapter);
|
||||
binding.pager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(binding.tabLayout) {
|
||||
|
||||
binding.pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
final FileDetailActivitiesFragment fragment = getFileDetailActivitiesFragment();
|
||||
|
@ -334,10 +345,11 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
|
|||
}
|
||||
});
|
||||
|
||||
TabLayout.Tab tab = binding.tabLayout.getTabAt(activeTab);
|
||||
if (tab != null) {
|
||||
tab.select();
|
||||
}
|
||||
binding.tabLayout.post(() -> {
|
||||
TabLayout.Tab tab1 = binding.tabLayout.getTabAt(activeTab);
|
||||
if (tab1 == null) return;
|
||||
tab1.select();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -79,9 +79,7 @@ import androidx.core.content.ContextCompat;
|
|||
import androidx.core.content.res.ResourcesCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import pl.droidsonroids.gif.GifDrawable;
|
||||
|
||||
|
@ -128,7 +126,7 @@ public class PreviewImageFragment extends FileFragment implements Injectable {
|
|||
* This method hides to client objects the need of doing the construction in two steps.
|
||||
*
|
||||
* @param imageFile An {@link OCFile} to preview as an image in the fragment
|
||||
* @param ignoreFirstSavedState Flag to work around an unexpected behaviour of {@link FragmentStateAdapter} ;
|
||||
* @param ignoreFirstSavedState Flag to work around an unexpected behaviour of { FragmentStateAdapter } ;
|
||||
* TODO better solution
|
||||
*/
|
||||
public static PreviewImageFragment newInstance(@NonNull OCFile imageFile,
|
||||
|
|
|
@ -135,10 +135,6 @@ class PreviewImagePagerAdapter : FragmentStateAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return imageFiles[position].hashCode().toLong()
|
||||
}
|
||||
|
||||
private fun addVideoOfLivePhoto(file: OCFile) {
|
||||
file.livePhotoVideo = selectedFile
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@
|
|||
app:tabTextColor="@color/text_color"
|
||||
app:tabInlineLabel="true" />
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
android:layout_marginBottom="@dimen/standard_margin"
|
||||
android:layout_marginTop="@dimen/standard_margin">
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/contentPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textColor="@color/primary_button_text_color"/>
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/contentPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
|
|
|
@ -5817,15 +5817,12 @@
|
|||
<sha256 value="66afb9f2eea39427f6f03c14c5b82ca240157e22b8b2a764f0a7c8ad87cb2d3e" origin="Generated by Gradle" reason="Artifact is not signed"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.nextcloud" name="android-library"
|
||||
version="cda1b08aa81b74201177f29c2326abee62f32c15">
|
||||
<component group="com.github.nextcloud" name="android-library" version="cda1b08aa81b74201177f29c2326abee62f32c15">
|
||||
<artifact name="android-library-cda1b08aa81b74201177f29c2326abee62f32c15.aar">
|
||||
<sha256 value="39c76af292201a94cf0753f296a18deb5512d88e97537f7c4e9a766ec50c1520"
|
||||
origin="Generated by Gradle" reason="Artifact is not signed" />
|
||||
<sha256 value="39c76af292201a94cf0753f296a18deb5512d88e97537f7c4e9a766ec50c1520" origin="Generated by Gradle" reason="Artifact is not signed"/>
|
||||
</artifact>
|
||||
<artifact name="android-library-cda1b08aa81b74201177f29c2326abee62f32c15.module">
|
||||
<sha256 value="c7686ef2125d141196bb3e1937a12f0647e5300accc132ddc11dfe37f9db66f2"
|
||||
origin="Generated by Gradle" reason="Artifact is not signed" />
|
||||
<sha256 value="c7686ef2125d141196bb3e1937a12f0647e5300accc132ddc11dfe37f9db66f2" origin="Generated by Gradle" reason="Artifact is not signed"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.nextcloud" name="android-library" version="e7a13d03c1e7549a301edb8b4b58d1c5dda84123">
|
||||
|
|
Loading…
Reference in a new issue