Return to second fragment from other fragments - android

I have 3 fragments in my MainActivity and I have set the second fragment as the default fragment (when you launch the app, you will see the second fragment).
I want to implement a code similar to OnBackPressed() that when the user presses the back button of phone and he/she is in 1st or 3rd fragment, instead of quiting the app, the application return to the second app.
MainActivity
public class MainActivity extends AppCompatActivity {
private ViewPager2 mPager;
private FragmentStateAdapter pagerAdapter;
private int num_page = 3;
private CircleIndicator3 mIndicator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPager = findViewById(R.id.viewpager);
pagerAdapter = new MyAdapter(this, num_page);
mPager.setAdapter(pagerAdapter);
mIndicator = findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
mIndicator.createIndicators(num_page,0);
mPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
mPager.setCurrentItem(1000, false);
mPager.setOffscreenPageLimit(1);
mPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
if (positionOffsetPixels == 0) {
mPager.setCurrentItem(position);
}
}
#Override
public void onPageSelected(int position) {
super.onPageSelected(position);
mIndicator.animatePageSelected(position%num_page);
}
});
mPager.setPageTransformer(new ViewPager2.PageTransformer() {
#Override
public void transformPage(#NonNull View page, float position) {
float myOffset = position;
if (mPager.getOrientation() == ViewPager2.ORIENTATION_HORIZONTAL) {
if (ViewCompat.getLayoutDirection(mPager) == ViewCompat.LAYOUT_DIRECTION_RTL) {
} else {
}
} else {
}
}
});
}
}
page.setTranslationY(myOffset);
page.setTranslationX(-myOffset);
page.setTranslationX(myOffset);
MyAdapter
public class MyAdapter extends FragmentStateAdapter {
public int mCount;
public MyAdapter(FragmentActivity fa, int count) {
super(fa);
mCount = count;
}
#NonNull
#Override
public Fragment createFragment(int position) {
int index = getRealPosition(position);
if (index == 0) return new FragFirst();
else if (index == 1) return new FragSecond();
else return new FragThird();
}
#Override
public int getItemCount() {
return 2000;
}
public int getRealPosition(int position) {
return position % mCount;
}
FragFirst, FragSecond and FragThird
public class FragFirst extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup, container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frame_1p, container, false);
}
}
Thanks

Generally, if you addToBackStack its transaction when you go to the 1st or the 3rd, then you can back to the 2nd when onBackPressed.
fragmentManager
.beginTransaction()
.replace(R.id.mainContainer, thirdFragment, ThirdFragment.TAG)
.addToBackStack(null)
.commit();

According to the Google's official training, you can define onBackPressed in the Activity like:
#Override
public void onBackPressed() {
if (viewPager.getCurrentItem() == 1) {
// If the user is currently looking at the 2nd page, allow the system to handle the
// Back button. This calls finish() on this activity and pops the back stack.
super.onBackPressed();
} else if (viewPager.getCurrentItem() == 0 || viewPager.getCurrentItem() == 2) {
// Select the 2nd page.
viewPager.setCurrentItem(1);
} else {
// There is no such a page number.
throw new IllegalArgumentException();
}
}
(* In addition to the above, the official training uses FragmentActivity rather than AppCompatActivity. I don't know whether it relates this problem or not.)

Related

ViewPager2 fragment click event

I'm trying to use viewpager2 in fragment and make each pages clickable.
But all solutions are not working for me.
I tried to make ListPageAdapter to extend RecyclerView.ViewHolder and custom viewHolder by using onCreateViewHolder and onBindViewHolder like recyclerView but it already extended FragmentStateAdapter for making fragment.
How can i make it clickable?
Here is my code
ListPageAdapter.java
public class ListPageAdapter extends FragmentStateAdapter {
public int mCount;
private LayoutInflater mInflate;
private OnListItemClickListener listener;
public ListPageAdapter(FragmentActivity fa, int count) {
super(fa);
mCount = count;
}
#NonNull
#Override
public Fragment createFragment(int position) {
int index = getRealPosition(position);
if(index==0) return new Swipe1();
else if(index==1) return new Swipe2();
else if(index==2) return new Swipe3();
else if(index==3) return new Swipe4();
else return new Swipe5();
}
#Override
public int getItemCount() {
return 2000;
}
public int getRealPosition(int position) { return position % mCount; }
}
TextSearch.java
public class TextSearch extends AppCompatActivity {
private Button submitBtn;
private CircleIndicator3 mIndicator;
private ViewPager2 mPager;
private FragmentStateAdapter pagerAdapter;
private int num_page = 5;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text_search);
submitBtn = findViewById(R.id.submitBtn);
//ViewPager2
mPager = findViewById(R.id.viewpager);
//Adapter
pagerAdapter = new ListPageAdapter(this, num_page);
//Indicator
mIndicator = findViewById(R.id.indicator);
//ViewPager Setting
mPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
mPager.setCurrentItem(1000);
mPager.setOffscreenPageLimit(3);
mPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
if (positionOffsetPixels == 0) {
mPager.setCurrentItem(position);
}
}
#Override
public void onPageSelected(int position) {
super.onPageSelected(position);
mIndicator.animatePageSelected(position % num_page);
}
});
final float pageMargin = getResources().getDimensionPixelOffset(R.dimen.pageMargin);
final float pageOffset = getResources().getDimensionPixelOffset(R.dimen.offset);
mPager.setPageTransformer(new ViewPager2.PageTransformer() {
#Override
public void transformPage(#NonNull View page, float position) {
float myOffset = position * -(2 * pageOffset + pageMargin);
if (mPager.getOrientation() == ViewPager2.ORIENTATION_HORIZONTAL) {
if (ViewCompat.getLayoutDirection(mPager) == ViewCompat.LAYOUT_DIRECTION_RTL) {
page.setTranslationX(-myOffset);
} else {
page.setTranslationX(myOffset);
}
} else {
page.setTranslationY(myOffset);
}
}
});
submitBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mPager.setAdapter(pagerAdapter);
mIndicator.setViewPager(mPager);
mIndicator.createIndicators(num_page, 0);
String sendText = textLine.getText().toString();
Log.d("calling", sendText);
FileUploadUtils.sendText(sendText);
}
});
}
}
You can use the same approach as for a common fragments. In Fragment(page of a pager) Override onAttach method and implement it like this.
#Override
public void onAttach(#NotNull Context context) {
super.onAttach(context);
try {
pageClickListener = ((PageClickListener) context);
} catch (Exception e) {
Log.e("SwipeFragment", "Root activity must implement PageClickListener");
}
}
And a root activity have to implement your listener.
public class MainActivity implements PageClickListener

Fragment animation issue

Working on simple animation in fragments. I have three fragments where I have to animate the views inside the fragment but the problem I am facing right now is that the animation is not working in the second fragment and when I revisit the fragment then also the animation is not working.
Adapter class
public class MyPageAdapter extends FragmentPagerAdapter {
private final int NUM_ITEMS = 3;
Context mContext;
public MyPageAdapter(FragmentManager fm, Context mContext) {
super(fm);
this.mContext = mContext;
}
public int getCount() {
return NUM_ITEMS;
}
public Fragment getItem(int position) {
// MainActivity.updatedposition(position);
if (position == 0)
return SliderOne.newInstance();
else if (position == 1)
return SliderTwo.newInstance();
else if (position == 2)
return SliderThree.newInstance();
return null;
}
}
Slider Activity
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {
}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
public void onPageSelected(int position) {
if (position == 0) {
SliderOne fragment = new SliderOne();
fragment.initAnimation(mContext);
}
else if (position == 1) {
SliderTwo fragment = new SliderTwo();
fragment.initAnimation(mContext);
}
if (position == 2) {
SliderThree fragment = new SliderThree();
fragment.initAnimation(mContext);
}
// Check if this is the page you want.
}
});
Fragment class
public class SliderThree extends Fragment implements PageSelectedAnimation {
ImageView logo;
TextView tv_appname;
CustomTextView tv_msg_2;
Animation smalltobig, nothingtocome, btnanim;
Context mContext;
public static SliderThree newInstance() {
SliderThree fragment = new SliderThree();
return fragment;
}
public SliderThree() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.slider_three, null);
mContext = getActivity();
logo = root.findViewById(R.id.logo);
tv_appname = root.findViewById(R.id.tv_appname);
tv_msg_2 = root.findViewById(R.id.tv_msg_2);
tv_msg_2.setText(Html.fromHtml("Message other users to negotiate<br><p>the perfect trade or deal.Always</p><p>use your best judgement when</p><p>buying or selling.</p>"));
return root;
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void initAnimation(Context mContext) {
smalltobig = AnimationUtils.loadAnimation(mContext, R.anim.smalltobig);
nothingtocome = AnimationUtils.loadAnimation(mContext, R.anim.nothingtocome);
btnanim = AnimationUtils.loadAnimation(mContext, R.anim.nothingtocome);
logo.setAnimation(smalltobig);
logo.setAnimation(nothingtocome);
tv_appname.setAnimation(btnanim);
}
}
interface created
public interface PageSelectedAnimation {
void initAnimation(Context context);
}
Error :-
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
at com.xxx.slider.SliderThree.initAnimation(SliderThree.java:79)
at com.xxx.activities.SliderActivity$2.onPageSelected(SliderActivity.java:103)
Sharing my code:
Fragment Code
I assume from the tags you are using that you are including those Fragments on a ViewPager.
ViewPager charges the current and the adjacents, so they are ready when needed. Therefore you animation runs out of the screen when it is charged.
I would suggest to use ViewPager.onPageChangeListener:
viewPager.addOnPageChangeListener(new OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
public void onPageSelected(int position) {
// Check if this is the page you want.
}
});
and run the animation method from there.
EDIT:
You can do that nicely creating and implementing an interface on every Fragment.
interface PageSelectedAnimation{
fun initAnimation()
}
.
public class SliderThree extends Fragment implements PageSelectedAnimation
and finally:
public void onPageSelected(int position) {
((PageSelectedAnimation)getYourFragment(position)).initAnimation()
}

It returns null when I use getView() to get root View of the Fragment in the ViewPager

I have an Activity that have two Fragments and those fragments are presented to user by a ViewPager. So, I created a class extends FragmentStatePagerAdapter for ViewPager's adapter (MainFragsAdapter class) and I overrided some methods of it. I want to get my fragment's instances in my ViewPager from host Activity and get current fragment's root View by getView() method.
I got the instances of fragments by typing followings in Activity's onCreate() But getView() of that instance returns null :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainFragsAdapter = new MainFragsAdapter(getSupportFragmentManager());
viewPager = (ViewPager)findViewById(R.id.Pager);
viewPager.setAdapter(mainFragsAdapter);
int index = viewPager.getCurrentItem();
if(index == 0) {
Fragment1 fragment = (Fragment1)viewPager.getAdapter().instantiateItem(viewPager, index);
View v = fragment.getView();
Log.e("Frag1View",v.toString()); //At this point, I'm getting NullPointerException
//because getView() returns null.(Fragment isn't null)
}else if(index == 1){
Fragment2 fragment =(Fragment2)viewPager.getAdapter().instantiateItem(viewPager, index);
}
}
My FragmentStatePagerAdapter :
public class MainFragsAdapter extends FragmentStatePagerAdapter {
private SparseArray<Fragment> fragments = new SparseArray<>();
private Fragment currentFragment;
private int NUM_ITEMS = 2;
public MainFragsAdapter(FragmentManager fm,Context context) {
super(fm);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public Fragment getItem(int position) {
if(position == 0){
this.currentFragment = Fragment1.createInstance();
}
if(position == 1){
this.currentFragment =Fragment2.createInstance();
}
return this.currentFragment;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment)super.instantiateItem(container,position);
fragments.put(position,fragment);
return fragment; }
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
fragments.remove(position);
super.destroyItem(container,position,object);
}
public Fragment getRegisteredFragment(int position) {
return fragments.get(position);
}
}
How can i solve this issue ? Thank you for helps.

How to save dynamically added pages in viewpager Android

With the help of Vivek Pratap Singh and astuetz codes from following questions(Remove Fragment Page from ViewPager in Android and Android saving dynamically added viewpager's fragment while coming back from another activity and reopening app),
In my previous question in stack overflow I used inbuild method onDestroy, as it looks like it will save all the dynamically added fragments in viewpager.
But it's not happening, I am able to see only one intial static page(i.e. fragment) when I restart my app or navigate to another activity and come back to my activity containing the viewpager with fragments.Could any one please help me on this question.
Here is my source code for your reference:
public class MainActivity extends FragmentActivity implements TextProvider {
private Button mAdd;
private Button mRemove;
private ViewPager mPager;
int position;
private MyPagerAdapter mAdapter;
private ArrayList<String> mEntries = new ArrayList<String>();
#Override
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putInt("currenItem", mPager.getCurrentItem());
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPager = (ViewPager) findViewById(R.id.pager);
if (savedInstanceState != null) {
mPager.setCurrentItem(savedInstanceState.getInt("currentItem", 0));
}
mEntries.add("page 1");
mAdd = (Button) findViewById(R.id.add);
mRemove = (Button) findViewById(R.id.remove);
mAdd.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
addNewItem();
}
});
mRemove.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
removeCurrentItem();
}
});
mAdapter = new MyPagerAdapter(this.getSupportFragmentManager(), this);
mPager.setAdapter(mAdapter);
mPager.setOffscreenPageLimit(3);
}
private void addNewItem() {
// int position = mPager.getCurrentItem();
mEntries.add("page ");
mAdapter.notifyDataSetChanged();
}
private void removeCurrentItem() {
int position = mPager.getCurrentItem();
if(position != 0){
mEntries.remove(position);
}else{
Toast.makeText(getApplicationContext(), "Sorry", Toast.LENGTH_LONG).show();
}
mAdapter.notifyDataSetChanged();
}
#Override
public String getTextForPosition(int position) {
return mEntries.get(position);
}
#Override
public int getCount() {
return mEntries.size();
}
private class MyPagerAdapter extends FragmentPagerAdapter {
private TextProvider mProvider;
private long baseId = 0;
public MyPagerAdapter(FragmentManager fm, TextProvider provider) {
super(fm);
this.mProvider = provider;
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return FragmentOne.newInstance(mProvider.getTextForPosition(position));
case 1:
return FragmentTwo.newInstance(mProvider.getTextForPosition(position));
case 2:
return FragmentThree.newInstance(mProvider.getTextForPosition(position));
default: return FragmentOne.newInstance(mProvider.getTextForPosition(position));
}
}
#Override
public int getCount() {
return mProvider.getCount();
}
//this is called when notifyDataSetChanged() is called
#Override
public int getItemPosition(Object object) {
// refresh all fragments when data set changed
return PagerAdapter.POSITION_NONE;
}
#Override
public long getItemId(int position) {
// give an ID different from position when position has been changed
return baseId + position;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
/**
* Notify that the position of a fragment has been changed.
* Create a new ID for each position to force recreation of the fragment
* #param n number of items which have been changed
*/
public void notifyChangeInPosition(int n) {
// shift the ID returned by getItemId outside the range of all previous fragments
baseId += getCount() + n;
}
}
}

How to save state of Fragments in ViewPager when orientation changes

I have an application that Implements ActionBarSherlock, it's mainly composed of
ViewPager with different content of fragments (for each page), with ViewPager indicator.
Here is my onCreate Method of the Activity that extends SherlockFragmentActivity
// Assume that tabs,sources,types are string arrays e.g. tabs = ["tab1","tab2","tab3"]
// types = ["listview","listview","webview"]
// according to the type of each tab, the type of content of the fragment associated to that tab is determined (e.g. WebView or ListView)
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.main);
srcContext = getBaseContext();
srcActivity = SaudiActivity.this;
int selectPos = 0;
Intent sender = getIntent();
FragmentPagerAdapter mAdapter = new NewsListAdapter(
getSupportFragmentManager());
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(mAdapter);
TabPageIndicator indicator = (TabPageIndicator) findViewById(R.id.indicator);
indicator.setViewPager(pager);
pager.setOffscreenPageLimit(tabs.length);
pager.setCurrentItem((tabs.length - 1));
currentPosition = (tabs.length - 1);
indicator.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
currentPosition = position;
if ((type[position] == "listview" || type[position]
.equals("listview")) && loaded[position] == false) {
loaded[position] = true;
getNews(listViews[position], position);
}
}
#Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
getSupportActionBar().setCustomView(R.layout.logo);
getSupportActionBar().setDisplayShowCustomEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
getSupportActionBar().setDisplayShowTitleEnabled(false);
getSupportActionBar().setDisplayShowHomeEnabled(false);
Context ctx = getSupportActionBar().getThemedContext();
SourcesAdapter adapter = new SourcesAdapter(ctx,
R.layout.navigation_list_item, src_name, icons, src_value);
}
Here are my News List Adapter (that creates the fragments),
public static class MyViewHolder {
public TextView title;
public ImageView icon;
}
class NewsListAdapter extends FragmentPagerAdapter {
public NewsListAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return new NewsFragment(MyActivity.this, position);
}
// This is the number of pages -- 5
#Override
public int getCount() {
return tabs.length;
}
// This is the title of the page that will apppear on the "tab"
public CharSequence getPageTitle(int position) {
return tabs[position];
}
}
public List<NewsItem> NewsItems;
Finally here's my NewsFragment:
public static class NewsFragment extends Fragment {
private int position;
public NewsFragment() {
}
public NewsFragment(Context ctx, int pos) {
this.position = pos;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = null;
if (type[position].equals("listview")) {
// Put a ListView in the Fragment
} else {
// Put a WebView in the Fragment
}
return view;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
}
Let the fragment handle it's state by overriding onSaveInstanceState and placing the necessary values into outState. Recover that state in onCreateView using savedInstanceState. Also I'm pretty sure that if you're using Actionbarsherlock fragments need to extend SherlockFragment rather than Fragment.

Categories

Resources