-
-
Save iammart/0f473a27015e45fe2b5a236d4efac651 to your computer and use it in GitHub Desktop.
Instagram like ViewPager implementation with bottom tab layout, without recreating fragments in fragment manager on tab select or back click. Implementation is prescribed for ViewPager inside fragment(more complex case) similar thing could be achieved for ViewPager in activity as well.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class BaseActivity extends AppCompatActivity { | |
public void moveBack() { | |
super.onBackPressed(); | |
} | |
public abstract void onBackWhenNoFragment(); | |
@Override | |
public void onBackPressed() { | |
BaseFragment currentFragment = (BaseFragment) getSupportFragmentManager() | |
.findFragmentById(R.id.fragment); | |
if (currentFragment != null) { | |
if (!currentFragment.onBackPressed()) { | |
onBackWhenNoFragment(); | |
} | |
} else { | |
moveBack(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class BaseFragment extends Fragment { | |
private BaseActivity activity = null; | |
public abstract boolean onBackPressed(); | |
public View.OnClickListener onBackClick = view -> activity().onBackPressed(); | |
// Retrieve activity | |
public BaseActivity activity(){ | |
if (activity == null) { | |
activity = (BaseActivity) getActivity(); | |
} | |
return activity; | |
} | |
@Override | |
public void onCreate(@Nullable Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
activity(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class HolderActivity extends BaseActivity{ | |
private static final String KEY_HOLDER_FRAGMENT = "holder_fragment"; | |
private Fragment holderFragment; | |
@Override | |
protected void onCreate(@Nullable Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
if (savedInstanceState != null) { | |
holderFragment = getSupportFragmentManager() | |
.getFragment(savedInstanceState, KEY_HOLDER_FRAGMENT); | |
} | |
replaceFragment(holderFragment); | |
} | |
@Override | |
protected void onSaveInstanceState(Bundle outState) { | |
super.onSaveInstanceState(outState); | |
FragmentManager fragmentManager = getSupportFragmentManager(); | |
if (holderFragment != null && holderFragment.isAdded()) { | |
fragmentManager.putFragment(outState, KEY_HOLDER_FRAGMENT, holderFragment); | |
} | |
} | |
@Override | |
public void onBackWhenNoFragment() { | |
moveTaskToBack(true); | |
} | |
public void replaceFragment(Fragment fragment) { | |
getSupportFragmentManager() | |
.beginTransaction() | |
.replace(R.id.fragment, fragment) | |
.commitAllowingStateLoss(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class HolderFragment extends BaseFragment implements TabLayout.OnTabSelectedListener { | |
public static final int HOME_POSITION = 0; | |
public static final int FEED_POSITION = 1; | |
public static final int CHANNEL_POSITION = 2; | |
public static final int PROFILE_POSITION = 3; | |
private static final String KEY_HOME_FRAGMENT = "home_fragment"; | |
private static final String KEY_FEED_FRAGMENT = "feed_fragment"; | |
private static final String KEY_CHANNEL_FRAGMENT = "channel_fragment"; | |
private static final String KEY_PROFILE_FRAGMENT = "profile_fragment"; | |
private static final String KEY_STACK = "my_stack"; | |
public List<TabLayout.Tab> tabs = new ArrayList<>(); | |
public static HolderFragment newInstance() { | |
Bundle args = new Bundle(); | |
HolderFragment fragment = new HolderFragment(); | |
fragment.setArguments(args); | |
return fragment; | |
} | |
private LinkedHashSet<Integer> stack = new LinkedHashSet<>(); | |
private TabLayout tabLayout; | |
private ArrayList<BaseFragment> fragments = new ArrayList<>(); | |
private String getKey(int position) { | |
switch (position) { | |
case HOME_POSITION: return KEY_HOME_FRAGMENT; | |
case FEED_POSITION: return KEY_FEED_FRAGMENT; | |
case CHANNEL_POSITION: return KEY_CHANNEL_FRAGMENT; | |
case PROFILE_POSITION: return KEY_PROFILE_FRAGMENT; | |
} | |
return KEY_HOME_FRAGMENT; | |
} | |
@Override | |
public void onCreate(@Nullable Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
if (savedInstanceState != null) { | |
FragmentManager fragmentManager = getChildFragmentManager(); | |
List<Integer> stackList = savedInstanceState.getIntegerArrayList(KEY_STACK); | |
if (stackList != null && !stackList.isEmpty()) { | |
stack.clear(); | |
stack.addAll(stackList); | |
} | |
fragments.clear(); | |
fragments.add((BaseFragment) fragmentManager.getFragment(savedInstanceState, | |
KEY_HOME_FRAGMENT)); | |
fragments.add((BaseFragment) fragmentManager.getFragment(savedInstanceState, | |
KEY_FEED_FRAGMENT)); | |
fragments.add((BaseFragment) fragmentManager.getFragment(savedInstanceState, | |
KEY_CHANNEL_FRAGMENT)); | |
fragments.add((BaseFragment) fragmentManager.getFragment(savedInstanceState, | |
KEY_PROFILE_FRAGMENT)); | |
} | |
if (fragments.isEmpty()) { | |
fragments.add(HomeFragment.newInstance()); | |
fragments.add(FeedFragment.newInstance()); | |
fragments.add(ChannelsHolderFragment.newInstance()); | |
fragments.add(ProfileFragment.newInstance()); | |
} | |
} | |
@Override | |
public void onSaveInstanceState(@NonNull Bundle outState) { | |
super.onSaveInstanceState(outState); | |
outState.putIntegerArrayList(KEY_STACK, new ArrayList<>(stack)); | |
FragmentManager fragmentManager = getChildFragmentManager(); | |
for (int i = 0; i < fragments.size(); i++) { | |
if (fragments.get(i).isAdded()) { | |
fragmentManager.putFragment(outState, getKey(i), fragments.get(i)); | |
} | |
} | |
} | |
@Nullable | |
@Override | |
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, | |
@Nullable Bundle savedInstanceState) { | |
super.onCreateView(inflater, container, savedInstanceState); | |
View rootView = inflater.inflate(R.layout.fragment_holder, container, false); | |
tabLayout = rootView.findViewById(R.id.tabLayout); | |
setTabLayout(); | |
initFragments(); | |
return rootView; | |
} | |
@Override | |
public void onDestroyView() { | |
super.onDestroyView(); | |
if (tabLayout != null) { | |
tabLayout.removeOnTabSelectedListener(this); | |
} | |
} | |
@Override | |
public boolean onBackPressed() { | |
try { | |
if (stack.isEmpty()) { | |
return false; | |
} else { | |
Integer lastElement = (Integer) stack.toArray()[stack.size() - 1]; | |
if (fragments.get(lastElement).onBackPressed()) { | |
return true; | |
} | |
if (stack.size() == 1) { | |
return false; | |
} | |
stack.remove(lastElement); | |
lastElement = (Integer) stack.toArray()[stack.size() - 1]; | |
tabs.get(lastElement).select(); | |
return true; | |
} | |
} catch (Exception e) { | |
return false; | |
} | |
} | |
private boolean set = false; | |
private void initFragments() { | |
if (!set) { | |
set = true; | |
FragmentManager fragmentManager = getChildFragmentManager(); | |
if (fragmentManager.getFragments().isEmpty()) { | |
for (BaseFragment fragment : fragments) { | |
fragmentManager.beginTransaction() | |
.add(R.id.frameLayout, fragment) | |
.commit(); | |
} | |
showFragment(); | |
} | |
} | |
} | |
private void showFragment() { | |
if (stack.isEmpty()){ | |
showFragment(HOME_POSITION); | |
} else { | |
showFragment((int) stack.toArray()[stack.size() - 1]); | |
} | |
} | |
private void showFragment(int position) { | |
stack.remove(position); | |
stack.add(position); | |
FragmentManager fragmentManager = getChildFragmentManager(); | |
for (int i = 0; i < fragments.size(); i++) { | |
if (i == position) { | |
fragmentManager.beginTransaction().show(fragments.get(i)).commit(); | |
} else { | |
fragmentManager.beginTransaction().hide(fragments.get(i)).commit(); | |
} | |
} | |
} | |
private View initTab(@DrawableRes int drawable) { | |
View tabView = getLayoutInflater().inflate(R.layout.layout_tab, null); | |
((AppCompatImageView) tabView.findViewById(R.id.icon)).setImageResource(drawable); | |
return tabView; | |
} | |
private void setTabLayout() { | |
if (!tabs.isEmpty()) { | |
tabs.clear(); | |
} | |
TabLayout.Tab homeTab = tabLayout.newTab(); | |
tabLayout.addTab(homeTab.setCustomView(initTab(R.drawable.ic_home))); | |
tabs.add(homeTab); | |
TabLayout.Tab feedTab = tabLayout.newTab(); | |
tabLayout.addTab(feedTab.setCustomView(initTab(R.drawable.ic_feed))); | |
tabs.add(feedTab); | |
TabLayout.Tab channelTab = tabLayout.newTab(); | |
tabLayout.addTab(channelTab.setCustomView(initTab(R.drawable.ic_channel))); | |
tabs.add(channelTab); | |
TabLayout.Tab profileTab = tabLayout.newTab(); | |
tabLayout.addTab(profileTab.setCustomView(initTab(R.drawable.ic_account_box))); | |
tabs.add(profileTab); | |
if (!stack.isEmpty()) { | |
tabs.get((int) stack.toArray()[stack.size() - 1]).select(); | |
} | |
tabLayout.addOnTabSelectedListener(this); | |
} | |
@Override | |
public void onTabSelected(TabLayout.Tab tab) { | |
showFragment(tab.getPosition()); | |
} | |
@Override | |
public void onTabUnselected(TabLayout.Tab tab) { | |
} | |
@Override | |
public void onTabReselected(TabLayout.Tab tab) { | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment