Migrate to ViewPager2 (#1544)
* migrate MainActivty to ViewPager2 * migrate AccountActivty to ViewPager2 * migrate ViewMediaActivty to ViewPager2 * migrate SearchActivity to ViewPager2 * checkin missing AccountPagerAdapter file * remove unused class ImageViewPager * replace SparseArray with MutableListmain
parent
20e406c413
commit
4d4c4cdb3d
@ -1,120 +0,0 @@ |
||||
/* Copyright 2017 Andrew Dawson |
||||
* |
||||
* This file is a part of Tusky. |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the |
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even |
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
||||
* Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not, |
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
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 com.keylesspalace.tusky.interfaces.RefreshableFragment; |
||||
|
||||
import java.util.HashSet; |
||||
import java.util.Set; |
||||
|
||||
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<Fragment> fragments = new SparseArray<>(TAB_COUNT); |
||||
|
||||
private final Set<Integer> pagesToRefresh = new HashSet<>(); |
||||
|
||||
public AccountPagerAdapter(FragmentManager manager, String accountId) { |
||||
super(manager); |
||||
this.accountId = accountId; |
||||
} |
||||
|
||||
public void setPageTitles(String[] titles) { |
||||
pageTitles = titles; |
||||
} |
||||
|
||||
@NonNull |
||||
@Override |
||||
public Fragment getItem(int position) { |
||||
switch (position) { |
||||
case 0: { |
||||
return TimelineFragment.newInstance(TimelineFragment.Kind.USER, accountId,false); |
||||
} |
||||
case 1: { |
||||
return TimelineFragment.newInstance(TimelineFragment.Kind.USER_WITH_REPLIES, accountId,false); |
||||
} |
||||
case 2: { |
||||
return TimelineFragment.newInstance(TimelineFragment.Kind.USER_PINNED, accountId,false); |
||||
} |
||||
case 3: { |
||||
return AccountMediaFragment.newInstance(accountId,false); |
||||
} |
||||
default: { |
||||
throw new AssertionError("Page " + position + " is out of AccountPagerAdapter bounds"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public int getCount() { |
||||
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); |
||||
if (pagesToRefresh.contains(position)) { |
||||
if (fragment instanceof RefreshableFragment) |
||||
((RefreshableFragment) fragment).refreshContent(); |
||||
pagesToRefresh.remove(position); |
||||
} |
||||
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); |
||||
} |
||||
|
||||
public void refreshContent(){ |
||||
for (int i=0;i<getCount();i++){ |
||||
Fragment fragment = getFragment(i); |
||||
if (fragment instanceof RefreshableFragment){ |
||||
((RefreshableFragment) fragment).refreshContent(); |
||||
} |
||||
else{ |
||||
pagesToRefresh.add(i); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,65 @@ |
||||
/* Copyright 2019 Tusky Contributors |
||||
* |
||||
* This file is a part of Tusky. |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the |
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even |
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
||||
* Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not, |
||||
* see <http://www.gnu.org/licenses>. */ |
||||
|
||||
package com.keylesspalace.tusky.pager |
||||
|
||||
import androidx.fragment.app.* |
||||
|
||||
import com.keylesspalace.tusky.fragment.AccountMediaFragment |
||||
import com.keylesspalace.tusky.fragment.TimelineFragment |
||||
import com.keylesspalace.tusky.interfaces.RefreshableFragment |
||||
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter |
||||
import java.lang.ref.WeakReference |
||||
|
||||
class AccountPagerAdapter( |
||||
activity: FragmentActivity, |
||||
private val accountId: String |
||||
) : FragmentStateAdapter(activity) { |
||||
|
||||
private val fragments = MutableList<WeakReference<Fragment>?>(TAB_COUNT) { null } |
||||
|
||||
override fun getItemCount() = TAB_COUNT |
||||
|
||||
override fun createFragment(position: Int): Fragment { |
||||
val fragment: Fragment = when (position) { |
||||
0 -> TimelineFragment.newInstance(TimelineFragment.Kind.USER, accountId, false) |
||||
1 -> TimelineFragment.newInstance(TimelineFragment.Kind.USER_WITH_REPLIES, accountId, false) |
||||
2 -> TimelineFragment.newInstance(TimelineFragment.Kind.USER_PINNED, accountId, false) |
||||
3 -> AccountMediaFragment.newInstance(accountId, false) |
||||
else -> throw AssertionError("Page $position is out of AccountPagerAdapter bounds") |
||||
} |
||||
|
||||
fragments[position] = WeakReference(fragment) |
||||
return fragment |
||||
} |
||||
|
||||
fun getFragment(position: Int): Fragment? { |
||||
return fragments[position]?.get() |
||||
} |
||||
|
||||
fun refreshContent() { |
||||
for (i in 0 until TAB_COUNT) { |
||||
val fragment = getFragment(i) |
||||
if (fragment != null && fragment is RefreshableFragment) { |
||||
(fragment as RefreshableFragment).refreshContent() |
||||
} |
||||
} |
||||
} |
||||
|
||||
companion object { |
||||
private const val TAB_COUNT = 4 |
||||
} |
||||
} |
@ -1,53 +1,42 @@ |
||||
package com.keylesspalace.tusky.pager |
||||
|
||||
import android.view.ViewGroup |
||||
import androidx.fragment.app.Fragment |
||||
import androidx.fragment.app.FragmentManager |
||||
import androidx.fragment.app.FragmentStatePagerAdapter |
||||
import com.keylesspalace.tusky.SharedElementTransitionListener |
||||
import androidx.fragment.app.FragmentActivity |
||||
import com.keylesspalace.tusky.ViewMediaAdapter |
||||
import com.keylesspalace.tusky.entity.Attachment |
||||
import com.keylesspalace.tusky.fragment.ViewMediaFragment |
||||
import java.util.* |
||||
import java.lang.ref.WeakReference |
||||
|
||||
class ImagePagerAdapter( |
||||
fragmentManager: FragmentManager, |
||||
activity: FragmentActivity, |
||||
private val attachments: List<Attachment>, |
||||
private val initialPosition: Int |
||||
) : FragmentStatePagerAdapter(fragmentManager), SharedElementTransitionListener { |
||||
) : ViewMediaAdapter(activity) { |
||||
|
||||
private var primaryItem: ViewMediaFragment? = null |
||||
private var didTransition = false |
||||
private val fragments = MutableList<WeakReference<ViewMediaFragment>?>(attachments.size) { null } |
||||
|
||||
override fun setPrimaryItem(container: ViewGroup, position: Int, item: Any) { |
||||
super.setPrimaryItem(container, position, item) |
||||
this.primaryItem = item as ViewMediaFragment |
||||
} |
||||
override fun getItemCount() = attachments.size |
||||
|
||||
override fun getItem(position: Int): Fragment { |
||||
return if (position >= 0 && position < attachments.size) { |
||||
override fun createFragment(position: Int): Fragment { |
||||
if (position >= 0 && position < attachments.size) { |
||||
// Fragment should not wait for or start transition if it already happened but we |
||||
// instantiate the same fragment again, e.g. open the first photo, scroll to the |
||||
// forth photo and then back to the first. The first fragment will trz to start the |
||||
// forth photo and then back to the first. The first fragment will try to start the |
||||
// transition and wait until it's over and it will never take place. |
||||
ViewMediaFragment.newInstance( |
||||
val fragment = ViewMediaFragment.newInstance( |
||||
attachment = attachments[position], |
||||
shouldStartPostponedTransition = !didTransition && position == initialPosition |
||||
) |
||||
fragments[position] = WeakReference(fragment) |
||||
return fragment |
||||
} else { |
||||
throw IllegalStateException() |
||||
} |
||||
} |
||||
|
||||
override fun getCount(): Int { |
||||
return attachments.size |
||||
} |
||||
|
||||
override fun getPageTitle(position: Int): CharSequence { |
||||
return String.format(Locale.getDefault(), "%d/%d", position + 1, attachments.size) |
||||
} |
||||
|
||||
override fun onTransitionEnd() { |
||||
override fun onTransitionEnd(position: Int) { |
||||
this.didTransition = true |
||||
primaryItem?.onTransitionEnd() |
||||
fragments[position]?.get()?.onTransitionEnd() |
||||
} |
||||
} |
||||
|
@ -1,45 +0,0 @@ |
||||
/* Copyright 2017 Andrew Dawson |
||||
* |
||||
* This file is a part of Tusky. |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the |
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even |
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
||||
* Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not, |
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.view; |
||||
|
||||
import android.content.Context; |
||||
import androidx.viewpager.widget.ViewPager; |
||||
import android.util.AttributeSet; |
||||
import android.view.MotionEvent; |
||||
|
||||
/** |
||||
* This class is entirely to address a known issue with com.github.chrisbanes.photoview.PhotoView. |
||||
* ViewPager will throw exceptions when a PhotoView is placed within it, so this subclass eats those |
||||
* exceptions. |
||||
*/ |
||||
public class ImageViewPager extends ViewPager { |
||||
public ImageViewPager(Context context) { |
||||
super(context); |
||||
} |
||||
|
||||
public ImageViewPager(Context context, AttributeSet attributeSet) { |
||||
super(context, attributeSet); |
||||
} |
||||
|
||||
@Override |
||||
public boolean onInterceptTouchEvent(MotionEvent ev) { |
||||
try { |
||||
return super.onInterceptTouchEvent(ev); |
||||
} catch (IllegalArgumentException e) { |
||||
return false; |
||||
} |
||||
} |
||||
} |
@ -1,5 +0,0 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:shape="rectangle"> |
||||
<solid android:color="@color/tab_page_margin_black" /> |
||||
</shape> |
@ -1,5 +0,0 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:shape="rectangle"> |
||||
<solid android:color="@color/tab_page_margin_dark" /> |
||||
</shape> |
@ -1,5 +0,0 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:shape="rectangle"> |
||||
<solid android:color="@color/tab_page_margin_light" /> |
||||
</shape> |
Loading…
Reference in new issue