From 01234bb94b7b5d3b23df96bbcc5cdca535ae2814 Mon Sep 17 00:00:00 2001 From: pandasoft0 Date: Mon, 8 Apr 2019 16:40:16 +0300 Subject: [PATCH] Add ability to scroll to top by tab click at the Account activity (#1146) * Issue: tuskyapp#1078 Add ability to scroll to top by tab click at the Account activity * Fix issue with scroll tabs other than current * Update scroll on click behavior * Update code formatting * Remove unused code * Move tab click listener from Fragments to Activities --- .../keylesspalace/tusky/AccountActivity.kt | 28 ++++++-- .../com/keylesspalace/tusky/MainActivity.java | 28 +++++--- .../conversation/ConversationsFragment.kt | 21 +++++- .../tusky/fragment/NotificationsFragment.java | 51 ++++---------- .../tusky/fragment/TimelineFragment.java | 69 +++++-------------- .../tusky/interfaces/ReselectableFragment.kt | 11 +++ .../tusky/pager/AccountPagerAdapter.java | 30 +++++++- .../tusky/pager/MainPagerAdapter.kt | 16 +++++ 8 files changed, 146 insertions(+), 108 deletions(-) create mode 100644 app/src/main/java/com/keylesspalace/tusky/interfaces/ReselectableFragment.kt diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt b/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt index 38061818..2741b3b4 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt @@ -41,12 +41,14 @@ import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.CollapsingToolbarLayout import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.snackbar.Snackbar +import com.google.android.material.tabs.TabLayout import com.keylesspalace.tusky.adapter.AccountFieldAdapter import com.keylesspalace.tusky.di.ViewModelFactory import com.keylesspalace.tusky.entity.Account import com.keylesspalace.tusky.entity.Relationship import com.keylesspalace.tusky.interfaces.ActionButtonActivity import com.keylesspalace.tusky.interfaces.LinkListener +import com.keylesspalace.tusky.interfaces.ReselectableFragment import com.keylesspalace.tusky.pager.AccountPagerAdapter import com.keylesspalace.tusky.util.* import com.keylesspalace.tusky.viewmodel.AccountViewModel @@ -104,6 +106,8 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF REQUESTED } + private var adapter: AccountPagerAdapter? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -174,7 +178,8 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF // Add a listener to change the toolbar icon color when it enters/exits its collapsed state. accountAppBarLayout.addOnOffsetChangedListener(object : AppBarLayout.OnOffsetChangedListener { - @AttrRes var priorAttribute = R.attr.account_toolbar_icon_tint_uncollapsed + @AttrRes + var priorAttribute = R.attr.account_toolbar_icon_tint_uncollapsed override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) { @@ -250,9 +255,9 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF accountFieldList.adapter = accountFieldAdapter // Setup the tabs and timeline pager. - val adapter = AccountPagerAdapter(supportFragmentManager, accountId) + adapter = AccountPagerAdapter(supportFragmentManager, accountId) val pageTitles = arrayOf(getString(R.string.title_statuses), getString(R.string.title_statuses_with_replies), getString(R.string.title_statuses_pinned), getString(R.string.title_media)) - adapter.setPageTitles(pageTitles) + adapter?.setPageTitles(pageTitles) accountFragmentViewPager.pageMargin = resources.getDimensionPixelSize(R.dimen.tab_page_margin) val pageMarginDrawable = ThemeUtils.getDrawable(this, R.attr.tab_page_margin_drawable, R.drawable.tab_page_margin_dark) @@ -260,10 +265,21 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF accountFragmentViewPager.adapter = adapter accountFragmentViewPager.offscreenPageLimit = 2 accountTabLayout.setupWithViewPager(accountFragmentViewPager) + accountTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { + override fun onTabReselected(tab: TabLayout.Tab?) { + tab?.position?.let { + (adapter?.getFragment(tab.position) as? ReselectableFragment)?.onReselect() + } + } + override fun onTabUnselected(tab: TabLayout.Tab?) {} + + override fun onTabSelected(tab: TabLayout.Tab?) {} + + }) val accountListClickListener = { v: View -> val type = when (v.id) { - R.id.accountFollowers-> AccountListActivity.Type.FOLLOWERS + R.id.accountFollowers -> AccountListActivity.Type.FOLLOWERS R.id.accountFollowing -> AccountListActivity.Type.FOLLOWS else -> throw AssertionError() } @@ -424,7 +440,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF } private fun updateFollowButton() { - if(isSelf) { + if (isSelf) { accountFollowButton.setText(R.string.action_edit_own_profile) return } @@ -449,7 +465,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF accountFollowButton.show() updateFollowButton() - if(isSelf) { + if (isSelf) { accountFloatingActionButton.hide() } else { accountFloatingActionButton.show() diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java index 2c581c26..93a1de5e 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java @@ -16,20 +16,25 @@ package com.keylesspalace.tusky; import androidx.lifecycle.Lifecycle; + import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; + import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.tabs.TabLayout; + import androidx.emoji.text.EmojiCompat; import androidx.fragment.app.Fragment; import androidx.core.content.ContextCompat; import androidx.viewpager.widget.ViewPager; import androidx.appcompat.app.AlertDialog; + import android.os.Handler; import android.util.Log; import android.view.KeyEvent; @@ -44,6 +49,7 @@ import com.keylesspalace.tusky.components.conversation.ConversationsRepository; import com.keylesspalace.tusky.db.AccountEntity; import com.keylesspalace.tusky.entity.Account; import com.keylesspalace.tusky.interfaces.ActionButtonActivity; +import com.keylesspalace.tusky.interfaces.ReselectableFragment; import com.keylesspalace.tusky.pager.MainPagerAdapter; import com.keylesspalace.tusky.util.CustomEmojiHelper; import com.keylesspalace.tusky.util.NotificationHelper; @@ -114,12 +120,13 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut private ViewPager viewPager; private int notificationTabPosition; + private MainPagerAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if(accountManager.getActiveAccount() == null) { + if (accountManager.getActiveAccount() == null) { // will be redirected to LoginActivity by BaseActivity return; } @@ -209,6 +216,12 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut @Override public void onTabReselected(TabLayout.Tab tab) { + if (adapter != null) { + Fragment fragment = adapter.getFragment(tab.getPosition()); + if (fragment instanceof ReselectableFragment) { + ((ReselectableFragment) fragment).onReselect(); + } + } } }); @@ -410,7 +423,7 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut private void setupTabs(boolean selectNotificationTab) { List tabs = accountManager.getActiveAccount().getTabPreferences(); - MainPagerAdapter adapter = new MainPagerAdapter(tabs, getSupportFragmentManager()); + adapter = new MainPagerAdapter(tabs, getSupportFragmentManager()); viewPager.setAdapter(adapter); tabLayout.setupWithViewPager(viewPager); @@ -420,9 +433,9 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut .setIcon(tabs.get(i).getIcon()) .setContentDescription(tabs.get(i).getText()); tabLayout.addTab(tab); - if(tabs.get(i).getId().equals(TabDataKt.NOTIFICATIONS)) { + if (tabs.get(i).getId().equals(TabDataKt.NOTIFICATIONS)) { notificationTabPosition = i; - if(selectNotificationTab) { + if (selectNotificationTab) { tab.select(); } } @@ -544,7 +557,7 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut .withSelectable(false) .withIcon(GoogleMaterial.Icon.gmd_person_add); drawer.addItemAtPosition(followRequestsItem, 3); - } else if(!me.getLocked()){ + } else if (!me.getLocked()) { drawer.removeItem(DRAWER_ITEM_FOLLOW_REQUESTS); } @@ -556,7 +569,7 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut List allAccounts = accountManager.getAllAccountsOrderedByActive(); - List profiles = new ArrayList<>(allAccounts.size()+1); + List profiles = new ArrayList<>(allAccounts.size() + 1); for (AccountEntity acc : allAccounts) { CharSequence emojifiedName = CustomEmojiHelper.emojifyString(acc.getDisplayName(), acc.getEmojis(), headerResult.getView()); @@ -574,7 +587,7 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut } // reuse the already existing "add account" item - for (IProfile profile: headerResult.getProfiles()) { + for (IProfile profile : headerResult.getProfiles()) { if (profile.getIdentifier() == DRAWER_ITEM_ADD_ACCOUNT) { profiles.add(profile); break; @@ -599,5 +612,4 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut public AndroidInjector supportFragmentInjector() { return fragmentInjector; } - } \ No newline at end of file diff --git a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt index 5dd6739c..b9933dc8 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt @@ -34,6 +34,7 @@ import com.keylesspalace.tusky.db.AppDatabase import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.di.ViewModelFactory import com.keylesspalace.tusky.fragment.SFragment +import com.keylesspalace.tusky.interfaces.ReselectableFragment import com.keylesspalace.tusky.interfaces.StatusActionListener import com.keylesspalace.tusky.util.NetworkState import com.keylesspalace.tusky.util.ThemeUtils @@ -41,7 +42,7 @@ import com.keylesspalace.tusky.util.hide import kotlinx.android.synthetic.main.fragment_timeline.* import javax.inject.Inject -class ConversationsFragment : SFragment(), StatusActionListener, Injectable { +class ConversationsFragment : SFragment(), StatusActionListener, Injectable, ReselectableFragment { @Inject lateinit var viewModelFactory: ViewModelFactory @@ -52,6 +53,8 @@ class ConversationsFragment : SFragment(), StatusActionListener, Injectable { private lateinit var adapter: ConversationAdapter + private var layoutManager: LinearLayoutManager? = null + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { viewModel = ViewModelProviders.of(this, viewModelFactory)[ConversationsViewModel::class.java] @@ -67,10 +70,11 @@ class ConversationsFragment : SFragment(), StatusActionListener, Injectable { val mediaPreviewEnabled = account?.mediaPreviewEnabled ?: true - adapter = ConversationAdapter(useAbsoluteTime, mediaPreviewEnabled,this, ::onTopLoaded, viewModel::retry) + adapter = ConversationAdapter(useAbsoluteTime, mediaPreviewEnabled, this, ::onTopLoaded, viewModel::retry) recyclerView.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL)) - recyclerView.layoutManager = LinearLayoutManager(view.context) + layoutManager = LinearLayoutManager(view.context) + recyclerView.layoutManager = layoutManager recyclerView.adapter = adapter (recyclerView.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false @@ -172,6 +176,17 @@ class ConversationsFragment : SFragment(), StatusActionListener, Injectable { } } + private fun jumpToTop() { + if (isAdded) { + layoutManager?.scrollToPosition(0) + recyclerView.stopScroll() + } + } + + override fun onReselect() { + jumpToTop() + } + companion object { fun newInstance() = ConversationsFragment() } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java index 8f046b80..795d990a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java @@ -27,8 +27,6 @@ import android.view.ViewGroup; import android.widget.ProgressBar; import com.google.android.material.floatingactionbutton.FloatingActionButton; -import com.google.android.material.tabs.TabLayout; -import com.keylesspalace.tusky.MainActivity; import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.adapter.NotificationsAdapter; import com.keylesspalace.tusky.adapter.StatusBaseViewHolder; @@ -43,6 +41,7 @@ import com.keylesspalace.tusky.di.Injectable; import com.keylesspalace.tusky.entity.Notification; import com.keylesspalace.tusky.entity.Status; import com.keylesspalace.tusky.interfaces.ActionButtonActivity; +import com.keylesspalace.tusky.interfaces.ReselectableFragment; import com.keylesspalace.tusky.interfaces.StatusActionListener; import com.keylesspalace.tusky.util.CollectionUtil; import com.keylesspalace.tusky.util.Either; @@ -97,7 +96,7 @@ public class NotificationsFragment extends SFragment implements SwipeRefreshLayout.OnRefreshListener, StatusActionListener, NotificationsAdapter.NotificationActionListener, - Injectable { + Injectable, ReselectableFragment { private static final String TAG = "NotificationF"; // logging tag private static final int LOAD_AT_ONCE = 30; @@ -138,7 +137,6 @@ public class NotificationsFragment extends SFragment implements private LinearLayoutManager layoutManager; private EndlessOnScrollListener scrollListener; private NotificationsAdapter adapter; - private TabLayout.OnTabSelectedListener onTabSelectedListener; private boolean hideFab; private boolean topLoading; private boolean bottomLoading; @@ -250,28 +248,9 @@ public class NotificationsFragment extends SFragment implements @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - - MainActivity activity = (MainActivity) getActivity(); + Activity activity = getActivity(); if (activity == null) throw new AssertionError("Activity is null"); - // MainActivity's layout is guaranteed to be inflated until onCreate returns. - TabLayout layout = activity.findViewById(R.id.tab_layout); - onTabSelectedListener = new TabLayout.OnTabSelectedListener() { - @Override - public void onTabSelected(TabLayout.Tab tab) { - } - - @Override - public void onTabUnselected(TabLayout.Tab tab) { - } - - @Override - public void onTabReselected(TabLayout.Tab tab) { - jumpToTop(); - } - }; - layout.addOnTabSelectedListener(onTabSelectedListener); - /* This is delayed until onActivityCreated solely because MainActivity.composeButton isn't * guaranteed to be set until then. * Use a modified scroll listener that both loads more notificationsEnabled as it goes, and hides @@ -323,19 +302,6 @@ public class NotificationsFragment extends SFragment implements }); } - @Override - public void onDestroyView() { - Activity activity = getActivity(); - if (activity == null) { - Log.e(TAG, "Activity is null"); - } else { - TabLayout tabLayout = activity.findViewById(R.id.tab_layout); - tabLayout.removeOnTabSelectedListener(onTabSelectedListener); - } - - super.onDestroyView(); - } - @Override public void onRefresh() { swipeRefreshLayout.setEnabled(true); @@ -634,8 +600,10 @@ public class NotificationsFragment extends SFragment implements } private void jumpToTop() { - layoutManager.scrollToPosition(0); - scrollListener.reset(); + if (isAdded()) { + layoutManager.scrollToPosition(0); + scrollListener.reset(); + } } private void sendFetchNotificationsRequest(String fromId, String uptoId, @@ -974,4 +942,9 @@ public class NotificationsFragment extends SFragment implements } } + + @Override + public void onReselect() { + jumpToTop(); + } } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java index ab0109cc..1d628a01 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java @@ -28,8 +28,6 @@ import android.view.ViewGroup; import android.widget.ProgressBar; import com.google.android.material.floatingactionbutton.FloatingActionButton; -import com.google.android.material.tabs.TabLayout; -import io.reactivex.Observable; import com.keylesspalace.tusky.AccountListActivity; import com.keylesspalace.tusky.BaseActivity; import com.keylesspalace.tusky.R; @@ -49,6 +47,7 @@ import com.keylesspalace.tusky.di.Injectable; import com.keylesspalace.tusky.entity.Filter; import com.keylesspalace.tusky.entity.Status; import com.keylesspalace.tusky.interfaces.ActionButtonActivity; +import com.keylesspalace.tusky.interfaces.ReselectableFragment; import com.keylesspalace.tusky.interfaces.StatusActionListener; import com.keylesspalace.tusky.network.MastodonApi; import com.keylesspalace.tusky.repository.Placeholder; @@ -66,8 +65,8 @@ import com.keylesspalace.tusky.view.BackgroundMessageView; import com.keylesspalace.tusky.view.EndlessOnScrollListener; import com.keylesspalace.tusky.viewdata.StatusViewData; -import java.util.ArrayList; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -94,6 +93,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.SimpleItemAnimator; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import at.connyduck.sparkbutton.helpers.Utils; +import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import kotlin.Unit; import kotlin.collections.CollectionsKt; @@ -107,7 +107,7 @@ import static com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvid public class TimelineFragment extends SFragment implements SwipeRefreshLayout.OnRefreshListener, StatusActionListener, - Injectable { + Injectable, ReselectableFragment { private static final String TAG = "TimelineF"; // logging tag private static final String KIND_ARG = "kind"; private static final String HASHTAG_OR_ID_ARG = "hashtag_or_id"; @@ -152,7 +152,6 @@ public class TimelineFragment extends SFragment implements private String hashtagOrId; private LinearLayoutManager layoutManager; private EndlessOnScrollListener scrollListener; - private TabLayout.OnTabSelectedListener onTabSelectedListener; private boolean filterRemoveReplies; private boolean filterRemoveReblogs; private boolean filterRemoveRegex; @@ -320,7 +319,7 @@ public class TimelineFragment extends SFragment implements @Override public void onResponse(@NonNull Call> call, @NonNull Response> response) { List filterList = response.body(); - if(response.isSuccessful() && filterList != null) { + if (response.isSuccessful() && filterList != null) { applyFilters(filterList, refresh); } else { Log.e(TAG, "Error getting filters from server"); @@ -352,7 +351,7 @@ public class TimelineFragment extends SFragment implements private static boolean filterContextMatchesKind(Kind kind, List filterContext) { // home, notifications, public, thread - switch(kind) { + switch (kind) { case HOME: return filterContext.contains(Filter.HOME); case PUBLIC_FEDERATED: @@ -436,27 +435,6 @@ public class TimelineFragment extends SFragment implements public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - if (jumpToTopAllowed()) { - TabLayout layout = requireActivity().findViewById(R.id.tab_layout); - if (layout != null) { - onTabSelectedListener = new TabLayout.OnTabSelectedListener() { - @Override - public void onTabSelected(TabLayout.Tab tab) { - } - - @Override - public void onTabUnselected(TabLayout.Tab tab) { - } - - @Override - public void onTabReselected(TabLayout.Tab tab) { - jumpToTop(); - } - }; - layout.addOnTabSelectedListener(onTabSelectedListener); - } - } - /* This is delayed until onActivityCreated solely because MainActivity.composeButton isn't * guaranteed to be set until then. */ if (actionButtonPresent()) { @@ -543,17 +521,6 @@ public class TimelineFragment extends SFragment implements } } - @Override - public void onDestroyView() { - if (jumpToTopAllowed()) { - TabLayout tabLayout = requireActivity().findViewById(R.id.tab_layout); - if (tabLayout != null) { - tabLayout.removeOnTabSelectedListener(onTabSelectedListener); - } - } - super.onDestroyView(); - } - @Override public void onRefresh() { swipeRefreshLayout.setEnabled(true); @@ -854,7 +821,7 @@ public class TimelineFragment extends SFragment implements return; } - if(statuses.size() == 0) { + if (statuses.size() == 0) { sendInitialRequest(); return; } @@ -895,19 +862,17 @@ public class TimelineFragment extends SFragment implements sendFetchTimelineRequest(null, null, null, FetchEnd.BOTTOM, -1); } - private boolean jumpToTopAllowed() { - return kind != Kind.TAG && kind != Kind.FAVOURITES; - } - private boolean actionButtonPresent() { return kind != Kind.TAG && kind != Kind.FAVOURITES && getActivity() instanceof ActionButtonActivity; } private void jumpToTop() { - layoutManager.scrollToPosition(0); - recyclerView.stopScroll(); - scrollListener.reset(); + if (isAdded()) { + layoutManager.scrollToPosition(0); + recyclerView.stopScroll(); + scrollListener.reset(); + } } private Call> getFetchCallByTimelineType(Kind kind, String tagOrId, String fromId, @@ -1325,13 +1290,12 @@ public class TimelineFragment extends SFragment implements @Nullable @Override public Object getChangePayload(@NonNull StatusViewData oldItem, @NonNull StatusViewData newItem) { - if (oldItem.deepEquals(newItem)){ + if (oldItem.deepEquals(newItem)) { //If items are equal - update timestamp only List payload = new ArrayList<>(); payload.add(StatusBaseViewHolder.Key.KEY_CREATED); return payload; - } - else + } else // If items are different - update a whole view holder return null; } @@ -1362,5 +1326,8 @@ public class TimelineFragment extends SFragment implements } - + @Override + public void onReselect() { + jumpToTop(); + } } diff --git a/app/src/main/java/com/keylesspalace/tusky/interfaces/ReselectableFragment.kt b/app/src/main/java/com/keylesspalace/tusky/interfaces/ReselectableFragment.kt new file mode 100644 index 00000000..c50178c1 --- /dev/null +++ b/app/src/main/java/com/keylesspalace/tusky/interfaces/ReselectableFragment.kt @@ -0,0 +1,11 @@ +package com.keylesspalace.tusky.interfaces + +/** + * Created by pandasoft (joelpyska1@gmail.com) on 04/04/2019. + */ +interface ReselectableFragment { + /** + * Call this method when tab reselected + */ + fun onReselect() +} \ No newline at end of file diff --git a/app/src/main/java/com/keylesspalace/tusky/pager/AccountPagerAdapter.java b/app/src/main/java/com/keylesspalace/tusky/pager/AccountPagerAdapter.java index 1acee62f..848fed99 100644 --- a/app/src/main/java/com/keylesspalace/tusky/pager/AccountPagerAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/pager/AccountPagerAdapter.java @@ -15,17 +15,25 @@ package com.keylesspalace.tusky.pager; +import android.util.SparseArray; +import android.view.ViewGroup; + import com.keylesspalace.tusky.fragment.AccountMediaFragment; import com.keylesspalace.tusky.fragment.TimelineFragment; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; public class AccountPagerAdapter extends FragmentPagerAdapter { + private static final int TAB_COUNT = 4; private String accountId; private String[] pageTitles; + private SparseArray fragments = new SparseArray<>(TAB_COUNT); + public AccountPagerAdapter(FragmentManager manager, String accountId) { super(manager); this.accountId = accountId; @@ -58,11 +66,31 @@ public class AccountPagerAdapter extends FragmentPagerAdapter { @Override public int getCount() { - return 4; + return TAB_COUNT; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + Object fragment = super.instantiateItem(container, position); + if (fragment instanceof Fragment) + fragments.put(position, (Fragment) fragment); + return fragment; + } + + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + super.destroyItem(container, position, object); + fragments.remove(position); } @Override public CharSequence getPageTitle(int position) { return pageTitles[position]; } + + @Nullable + public Fragment getFragment(int position) { + return fragments.get(position); + } } diff --git a/app/src/main/java/com/keylesspalace/tusky/pager/MainPagerAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/pager/MainPagerAdapter.kt index 668faf54..7f0558c3 100644 --- a/app/src/main/java/com/keylesspalace/tusky/pager/MainPagerAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/pager/MainPagerAdapter.kt @@ -15,6 +15,8 @@ package com.keylesspalace.tusky.pager +import android.util.SparseArray +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter @@ -22,6 +24,7 @@ import androidx.viewpager.widget.PagerAdapter import com.keylesspalace.tusky.TabData class MainPagerAdapter(val tabs: List, manager: FragmentManager) : FragmentPagerAdapter(manager) { + private val fragments = SparseArray(tabs.size) override fun getItem(position: Int): Fragment { val tab = tabs[position] @@ -44,4 +47,17 @@ class MainPagerAdapter(val tabs: List, manager: FragmentManager) : Frag return PagerAdapter.POSITION_NONE } + override fun instantiateItem(container: ViewGroup, position: Int): Any { + val fragment = super.instantiateItem(container, position) + if (fragment is Fragment) + fragments.put(position, fragment) + return fragment + } + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + super.destroyItem(container, position, `object`) + fragments.remove(position) + } + + fun getFragment(position: Int): Fragment? = fragments[position] }