Compare commits

...

6 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] db98b41aa7 Use safe fragment handling for AllMediaActivity page changes
Agent-Logs-Url: https://github.com/ArcaneChat/android/sessions/27346299-b840-4970-893f-f438f9b94981

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-05-11 20:49:33 +00:00
copilot-swe-agent[bot] 877545518b Lazy-create pager fragments in AllMediaActivity without tag lookup
Agent-Logs-Url: https://github.com/ArcaneChat/android/sessions/27346299-b840-4970-893f-f438f9b94981

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-05-11 20:47:27 +00:00
copilot-swe-agent[bot] 0cff1066e1 Remove internal fragment tag lookup in AllMediaActivity pager
Agent-Logs-Url: https://github.com/ArcaneChat/android/sessions/27346299-b840-4970-893f-f438f9b94981

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-05-11 20:45:32 +00:00
copilot-swe-agent[bot] 88f528e8b8 QrActivity: replace fragile fragment tag lookups with direct references
Agent-Logs-Url: https://github.com/ArcaneChat/android/sessions/2ccd1bbb-e291-4d2d-b541-964679f4188e

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-05-11 17:20:41 +00:00
copilot-swe-agent[bot] ee3dcd38a6 Fix review issues: NO_POSITION and setCurrentItem animate param
Agent-Logs-Url: https://github.com/ArcaneChat/android/sessions/de374ae1-3e38-498d-8896-624a25191eb3

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-05-11 14:16:37 +00:00
copilot-swe-agent[bot] 1af9e87af0 Migrate from ViewPager to ViewPager2
Agent-Logs-Url: https://github.com/ArcaneChat/android/sessions/de374ae1-3e38-498d-8896-624a25191eb3

Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
2026-05-11 14:14:28 +00:00
12 changed files with 149 additions and 211 deletions
+1
View File
@@ -279,6 +279,7 @@ dependencies {
implementation "androidx.media3:media3-session:$media3_version"
implementation "androidx.media3:media3-ui:$media3_version"
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
implementation 'androidx.viewpager2:viewpager2:1.1.0'
implementation 'com.google.zxing:core:3.3.0' // fixed version to support SDK<24
implementation ('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false } // QR Code scanner
implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.1' // used as JSON library
@@ -4,7 +4,6 @@ import android.content.ComponentName;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
@@ -12,18 +11,19 @@ import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProvider;
import androidx.media3.session.MediaController;
import androidx.media3.session.SessionCommand;
import androidx.media3.session.SessionToken;
import androidx.viewpager.widget.ViewPager;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEvent;
import com.b44t.messenger.DcMsg;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.ArrayList;
import org.thoughtcrime.securesms.components.audioplay.AudioPlaybackViewModel;
@@ -64,7 +64,7 @@ public class AllMediaActivity extends PassphraseRequiredActionBarActivity
private final ArrayList<TabData> tabs = new ArrayList<>();
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
private ViewPager2 viewPager;
private @Nullable MediaController mediaController;
private ListenableFuture<MediaController> mediaControllerFuture;
@@ -98,8 +98,20 @@ public class AllMediaActivity extends PassphraseRequiredActionBarActivity
isGlobalGallery() ? R.string.menu_all_media : R.string.apps_and_media);
}
this.tabLayout.setupWithViewPager(viewPager);
this.viewPager.setAdapter(new AllMediaPagerAdapter(getSupportFragmentManager()));
AllMediaPagerAdapter adapter = new AllMediaPagerAdapter(this);
this.viewPager.setAdapter(adapter);
this.viewPager.registerOnPageChangeCallback(
new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
adapter.onPageChanged(position);
}
});
new TabLayoutMediator(
this.tabLayout,
this.viewPager,
(tab, position) -> tab.setText(getString(tabs.get(position).title)))
.attach();
if (getIntent().getBooleanExtra(FORCE_GALLERY, false)) {
this.viewPager.setCurrentItem(1, false);
}
@@ -186,31 +198,16 @@ public class AllMediaActivity extends PassphraseRequiredActionBarActivity
return contactId == 0 && chatId == 0;
}
private class AllMediaPagerAdapter extends FragmentStatePagerAdapter {
private Object currentFragment = null;
private class AllMediaPagerAdapter extends FragmentStateAdapter {
private int currentPosition = -1;
AllMediaPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
super.setPrimaryItem(container, position, object);
if (currentFragment != null && currentFragment != object) {
ActionMode action = null;
if (currentFragment instanceof MessageSelectorFragment) {
action = ((MessageSelectorFragment) currentFragment).getActionMode();
}
if (action != null) {
action.finish();
}
}
currentFragment = object;
AllMediaPagerAdapter(FragmentActivity activity) {
super(activity);
}
@NonNull
@Override
public Fragment getItem(int position) {
public Fragment createFragment(int position) {
TabData data = tabs.get(position);
Fragment fragment;
Bundle args = new Bundle();
@@ -233,13 +230,24 @@ public class AllMediaActivity extends PassphraseRequiredActionBarActivity
}
@Override
public int getCount() {
public int getItemCount() {
return tabs.size();
}
@Override
public CharSequence getPageTitle(int position) {
return getString(tabs.get(position).title);
void onPageChanged(int newPosition) {
if (currentPosition != -1 && currentPosition != newPosition) {
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
if (!(fragment instanceof MessageSelectorFragment)) {
continue;
}
ActionMode action = ((MessageSelectorFragment) fragment).getActionMode();
if (action != null) {
action.finish();
}
}
}
currentPosition = newPosition;
}
}
@@ -33,14 +33,13 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcMediaGalleryElement;
@@ -88,7 +87,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
@Nullable private DcMsg messageRecord;
private DcContext dcContext;
private MediaItem initialMedia;
private ViewPager mediaPager;
private ViewPager2 mediaPager;
private Recipient conversationRecipient;
private boolean leftIsRecent;
@@ -190,7 +189,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
private void initializeViews() {
mediaPager = findViewById(R.id.media_pager);
mediaPager.setOffscreenPageLimit(1);
mediaPager.addOnPageChangeListener(new ViewPagerListener());
mediaPager.registerOnPageChangeCallback(new ViewPagerListener());
}
private void initializeResources() {
@@ -261,7 +260,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
private int cleanupMedia() {
int restartItem = mediaPager.getCurrentItem();
mediaPager.removeAllViews();
mediaPager.setAdapter(null);
return restartItem;
@@ -483,11 +481,11 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
@SuppressWarnings("ConstantConditions")
DcMediaPagerAdapter adapter =
new DcMediaPagerAdapter(this, GlideApp.with(this), getWindow(), data, leftIsRecent);
mediaPager.setAdapter(adapter);
adapter.setActive(true);
mediaPager.setAdapter(adapter);
if (restartItem < 0) mediaPager.setCurrentItem(data.getPosition());
else mediaPager.setCurrentItem(restartItem);
if (restartItem < 0) mediaPager.setCurrentItem(data.getPosition(), false);
else mediaPager.setCurrentItem(restartItem, false);
}
}
@@ -526,7 +524,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
}
}
private static class SingleItemPagerAdapter extends PagerAdapter implements MediaItemAdapter {
private static class SingleItemPagerAdapter extends RecyclerView.Adapter<SingleItemPagerAdapter.MediaViewHolder> implements MediaItemAdapter {
private final GlideRequests glideRequests;
private final Window window;
@@ -555,37 +553,29 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
}
@Override
public int getCount() {
public int getItemCount() {
return 1;
}
@NonNull
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
public MediaViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new MediaViewHolder(inflater.inflate(R.layout.media_view_page, parent, false));
}
@Override
public @NonNull Object instantiateItem(@NonNull ViewGroup container, int position) {
View itemView = inflater.inflate(R.layout.media_view_page, container, false);
MediaView mediaView = itemView.findViewById(R.id.media_view);
public void onBindViewHolder(@NonNull MediaViewHolder holder, int position) {
try {
mediaView.set(glideRequests, window, uri, name, mediaType, size, true);
holder.mediaView.set(glideRequests, window, uri, name, mediaType, size, true);
} catch (IOException e) {
Log.w(TAG, e);
}
container.addView(itemView);
return itemView;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
MediaView mediaView = ((FrameLayout) object).findViewById(R.id.media_view);
mediaView.cleanup();
container.removeView((FrameLayout) object);
public void onViewRecycled(@NonNull MediaViewHolder holder) {
super.onViewRecycled(holder);
holder.mediaView.cleanup();
}
@Override
@@ -595,9 +585,18 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
@Override
public void pause(int position) {}
static class MediaViewHolder extends RecyclerView.ViewHolder {
final MediaView mediaView;
MediaViewHolder(@NonNull View itemView) {
super(itemView);
mediaView = itemView.findViewById(R.id.media_view);
}
}
}
private static class DcMediaPagerAdapter extends PagerAdapter implements MediaItemAdapter {
private static class DcMediaPagerAdapter extends RecyclerView.Adapter<DcMediaPagerAdapter.MediaViewHolder> implements MediaItemAdapter {
private final WeakHashMap<Integer, MediaView> mediaViews = new WeakHashMap<>();
@@ -630,21 +629,21 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
}
@Override
public int getCount() {
public int getItemCount() {
if (!active) return 0;
else return gallery.getCount();
}
@NonNull
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
public MediaViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView =
LayoutInflater.from(context).inflate(R.layout.media_view_page, parent, false);
return new MediaViewHolder(itemView);
}
@Override
public @NonNull Object instantiateItem(@NonNull ViewGroup container, int position) {
View itemView =
LayoutInflater.from(context).inflate(R.layout.media_view_page, container, false);
MediaView mediaView = itemView.findViewById(R.id.media_view);
public void onBindViewHolder(@NonNull MediaViewHolder holder, int position) {
boolean autoplay = position == autoPlayPosition;
int cursorPosition = getCursorPosition(position);
@@ -656,7 +655,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
try {
//noinspection ConstantConditions
mediaView.set(
holder.mediaView.set(
glideRequests,
window,
Uri.fromFile(msg.getFileAsFile()),
@@ -668,19 +667,17 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
Log.w(TAG, e);
}
mediaViews.put(position, mediaView);
container.addView(itemView);
return itemView;
mediaViews.put(position, holder.mediaView);
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
MediaView mediaView = ((FrameLayout) object).findViewById(R.id.media_view);
mediaView.cleanup();
mediaViews.remove(position);
container.removeView((FrameLayout) object);
public void onViewRecycled(@NonNull MediaViewHolder holder) {
super.onViewRecycled(holder);
int pos = holder.getBindingAdapterPosition();
if (pos != RecyclerView.NO_POSITION) {
mediaViews.remove(pos);
}
holder.mediaView.cleanup();
}
public MediaItem getMediaItemFor(int position) {
@@ -710,6 +707,15 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
if (leftIsRecent) return position;
else return gallery.getCount() - 1 - position;
}
static class MediaViewHolder extends RecyclerView.ViewHolder {
final MediaView mediaView;
MediaViewHolder(@NonNull View itemView) {
super(itemView);
mediaView = itemView.findViewById(R.id.media_view);
}
}
}
private static class MediaItem {
@@ -1,31 +0,0 @@
package org.thoughtcrime.securesms.components;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.ViewPager;
import org.thoughtcrime.securesms.components.viewpager.HackyViewPager;
/** An implementation of {@link ViewPager} that disables swiping when the view is disabled. */
public class ControllableViewPager extends HackyViewPager {
public ControllableViewPager(@NonNull Context context) {
super(context);
}
public ControllableViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return isEnabled() && super.onTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return isEnabled() && super.onInterceptTouchEvent(ev);
}
}
@@ -1,8 +1,8 @@
package org.thoughtcrime.securesms.components.viewpager;
import androidx.viewpager.widget.ViewPager;
import androidx.viewpager2.widget.ViewPager2;
public abstract class ExtendedOnPageChangedListener implements ViewPager.OnPageChangeListener {
public abstract class ExtendedOnPageChangedListener extends ViewPager2.OnPageChangeCallback {
private Integer currentPage = null;
@@ -1,41 +0,0 @@
package org.thoughtcrime.securesms.components.viewpager;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import androidx.viewpager.widget.ViewPager;
/**
* Hacky fix for http://code.google.com/p/android/issues/detail?id=18990
*
* <p>ScaleGestureDetector seems to mess up the touch events, which means that ViewGroups which make
* use of onInterceptTouchEvent throw a lot of IllegalArgumentException: pointerIndex out of range.
*
* <p>There's not much I can do in my code for now, but we can mask the result by just catching the
* problem and ignoring it.
*
* @author Chris Banes
*/
public class HackyViewPager extends ViewPager {
private static final String TAG = "HackyViewPager";
public HackyViewPager(Context context) {
super(context);
}
public HackyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
Log.w(TAG, e);
return false;
}
}
}
@@ -15,10 +15,11 @@ import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
import androidx.fragment.app.FragmentActivity;
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 com.google.zxing.BinaryBitmap;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
@@ -48,8 +49,9 @@ public class QrActivity extends BaseActionBarActivity implements View.OnClickLis
private static final int TAB_SCAN = 1;
private TabLayout tabLayout;
private ViewPager viewPager;
private ViewPager2 viewPager;
private QrShowFragment qrShowFragment;
private ProfilePagerAdapter adapter;
private boolean scanRelay;
@Override
@@ -68,7 +70,7 @@ public class QrActivity extends BaseActionBarActivity implements View.OnClickLis
qrShowFragment = new QrShowFragment(this);
tabLayout = ViewUtil.findById(this, R.id.tab_layout);
viewPager = ViewUtil.findById(this, R.id.pager);
ProfilePagerAdapter adapter = new ProfilePagerAdapter(this, getSupportFragmentManager());
adapter = new ProfilePagerAdapter(this);
viewPager.setAdapter(adapter);
setSupportActionBar(ViewUtil.findById(this, R.id.toolbar));
@@ -76,38 +78,36 @@ public class QrActivity extends BaseActionBarActivity implements View.OnClickLis
getSupportActionBar().setTitle(scanRelay ? R.string.add_transport : R.string.menu_new_contact);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager.setCurrentItem(scanRelay ? TAB_SCAN : TAB_SHOW);
viewPager.setCurrentItem(scanRelay ? TAB_SCAN : TAB_SHOW, false);
if (scanRelay) tabLayout.setVisibility(View.GONE);
viewPager.addOnPageChangeListener(
new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(
int position, float positionOffset, int positionOffsetPixels) {}
viewPager.registerOnPageChangeCallback(
new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
QrActivity.this.invalidateOptionsMenu();
checkPermissions(position, adapter, viewPager);
checkPermissions(position, viewPager);
}
@Override
public void onPageScrollStateChanged(int state) {}
});
tabLayout.setupWithViewPager(viewPager);
new TabLayoutMediator(
tabLayout,
viewPager,
(tab, position) -> tab.setText(adapter.getPageTitle(position)))
.attach();
}
private void checkPermissions(int position, ProfilePagerAdapter adapter, ViewPager viewPager) {
private void checkPermissions(int position, ViewPager2 viewPager) {
if (position == TAB_SCAN) {
Permissions.with(QrActivity.this)
.request(Manifest.permission.CAMERA)
.ifNecessary()
.withPermanentDenialDialog(getString(R.string.perm_explain_access_to_camera_denied))
.onAllGranted(
() ->
((QrScanFragment) adapter.getItem(TAB_SCAN))
.handleQrScanWithPermissions(QrActivity.this))
() -> {
QrScanFragment qrScanFrag = adapter.getQrScanFragment();
qrScanFrag.handleQrScanWithPermissions(QrActivity.this);
})
.onAnyDenied(
() -> {
if (scanRelay) {
@@ -225,47 +225,41 @@ public class QrActivity extends BaseActionBarActivity implements View.OnClickLis
@Override
public void onClick(View v) {
viewPager.setCurrentItem(TAB_SCAN);
viewPager.setCurrentItem(TAB_SCAN, true);
}
private class ProfilePagerAdapter extends FragmentStatePagerAdapter {
private class ProfilePagerAdapter extends FragmentStateAdapter {
private final QrActivity activity;
private final QrScanFragment qrScanFragment = new QrScanFragment();
ProfilePagerAdapter(QrActivity activity, FragmentManager fragmentManager) {
super(fragmentManager, FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
this.activity = activity;
ProfilePagerAdapter(FragmentActivity activity) {
super(activity);
}
QrScanFragment getQrScanFragment() {
return qrScanFragment;
}
@NonNull
@Override
public Fragment getItem(int position) {
Fragment fragment;
public Fragment createFragment(int position) {
switch (position) {
case TAB_SHOW:
fragment = activity.qrShowFragment;
break;
return qrShowFragment;
default:
fragment = new QrScanFragment();
break;
return qrScanFragment;
}
return fragment;
}
@Override
public int getCount() {
public int getItemCount() {
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
CharSequence getPageTitle(int position) {
switch (position) {
case TAB_SHOW:
return getString(R.string.qrshow_title);
default:
return getString(R.string.qrscan_title);
}
@@ -20,10 +20,10 @@ import android.view.MenuItem;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
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 org.thoughtcrime.securesms.R;
public class StickerSelectActivity extends FragmentActivity
@@ -47,15 +47,16 @@ public class StickerSelectActivity extends FragmentActivity
super.onCreate(savedInstanceState);
setContentView(R.layout.scribble_select_sticker_activity);
ViewPager viewPager = findViewById(R.id.camera_sticker_pager);
viewPager.setAdapter(new StickerPagerAdapter(getSupportFragmentManager(), this));
ViewPager2 viewPager = findViewById(R.id.camera_sticker_pager);
StickerPagerAdapter adapter = new StickerPagerAdapter(this, this);
viewPager.setAdapter(adapter);
TabLayout tabLayout = findViewById(R.id.camera_sticker_tabs);
tabLayout.setupWithViewPager(viewPager);
for (int i = 0; i < tabLayout.getTabCount(); i++) {
tabLayout.getTabAt(i).setIcon(TAB_TITLES[i]);
}
new TabLayoutMediator(
tabLayout,
viewPager,
(tab, position) -> tab.setIcon(TAB_TITLES[position]))
.attach();
}
@Override
@@ -75,13 +76,13 @@ public class StickerSelectActivity extends FragmentActivity
finish();
}
static class StickerPagerAdapter extends FragmentStatePagerAdapter {
static class StickerPagerAdapter extends FragmentStateAdapter {
private final Fragment[] fragments;
StickerPagerAdapter(
FragmentManager fm, StickerSelectFragment.StickerSelectionListener listener) {
super(fm);
FragmentActivity activity, StickerSelectFragment.StickerSelectionListener listener) {
super(activity);
this.fragments =
new Fragment[] {
@@ -98,12 +99,12 @@ public class StickerSelectActivity extends FragmentActivity
}
@Override
public Fragment getItem(int position) {
public Fragment createFragment(int position) {
return fragments[position];
}
@Override
public int getCount() {
public int getItemCount() {
return fragments.length;
}
}
+1 -1
View File
@@ -37,7 +37,7 @@
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
+1 -1
View File
@@ -37,7 +37,7 @@
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -7,7 +7,7 @@
android:fitsSystemWindows="true"
android:background="@color/gray95">
<org.thoughtcrime.securesms.components.viewpager.HackyViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/media_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
@@ -21,7 +21,7 @@
app:tabSelectedTextColor="@color/white"
app:tabMode="fixed" />
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/camera_sticker_pager"
android:layout_width="match_parent"
android:layout_height="0px"