ViewPager inside a Fragment (NestedFragments) - java

My app has the main activity with a Navigation Drawer, that allow the application to navigate between Fragments. Each item list of the navigation drawer shows a fragment.
In one of those Fragment I want a ViewPager, and here is where I got stuck. If I'm not wrong, this is a Fragment inside another Fragment (Nested Fragments) but I can't make this work.
This is the code of the fragment that contains the ViewPager
Seccion1.java
import android.app.Fragment;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public class Seccion1 extends Fragment {
ViewPager vp;
private List<android.support.v4.app.Fragment> getFragments(){
List<android.support.v4.app.Fragment> list = new ArrayList<android.support.v4.app.Fragment>();
list.add(ModelFragment.newInstance("Hola como andas", "descriociones"));
list.add(ModelFragment.newInstance("0895452125x", "#FFFFEF59"));
list.add(ModelFragment.newInstance("22 Mart", "#FF9C63FF"));
list.add(ModelFragment.newInstance("Sak", "#72a83b"));
list.add(ModelFragment.newInstance("Android Studio", "#a83b97"));
return list;
}
//#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.seccion1, container, false);
vp = (ViewPager)rootView.findViewById(R.id.vp);
//vp.setPageTransformer(true, new RotateDownTransformer());
ControllerFragment cf = new ControllerFragment(getChildFragmentManager(), getFragments());
vp.setAdapter(cf);
return rootView;
}
}
I don't know how to fix this line:
ControllerFragment cf = new ControllerFragment(getChildFragmentManager(), getFragments());
Here the ControllerFragment code
ControllerFragment.java
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.List;
public class ControllerFragment extends FragmentPagerAdapter {
List<Fragment> fragments;
Context context;
public ControllerFragment(FragmentManager fm, List<Fragment> fragments){
super(fm);
this.fragments = fragments;
}
public Fragment getItem(int position){
return fragments.get(position);
}
public int getCount(){
return fragments.size();
}
public Object instantiateItem(View view, int position){
RelativeLayout relativeLayout = (RelativeLayout)view.inflate(context, R.layout.custom_fragment, null);
TextView tv_text = (TextView)relativeLayout.findViewById(R.id.tv_text);
TextView tv_description = (TextView)relativeLayout.findViewById(R.id.tv_description);
((ViewPager) view).addView(relativeLayout);
return relativeLayout;
}
}

Change this
import android.app.Fragment;
to
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;

Related

Problem with fragment communication(Attempt to invoke virtual method)

I have a tabbed activity with 2 fragments. I'm trying to transmit a string from the first fragment to the second fragment but I'm getting NULL POINTER EXCEPTION.
Here is the MainActivity.java:
package com.example.myapplication;
import android.os.Bundle;
import com.google.android.material.tabs.TabLayout;
import androidx.fragment.app.FragmentTransaction;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.AppCompatActivity;
import com.example.myapplication.ui.main.SectionsPagerAdapter;
public class MainActivity extends AppCompatActivity implements Frag1.Exchange {
private static final String TAG = "MainActivity";
private SectionsPagerAdapter sectionsPagerAdapter;
private ViewPager viewPager;
private TabLayout tabLayout;
private void setupViewPager(ViewPager viewPager){
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
sectionsPagerAdapter.addFragment(new Frag1(), "FirstTab");
sectionsPagerAdapter.addFragment(new Frag2(), "SecondTab");
viewPager.setAdapter(sectionsPagerAdapter);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
viewPager = (ViewPager) findViewById(R.id.view_pager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
#Override
public void stringExchange(String s) {
Frag2 frag2 = (Frag2) getSupportFragmentManager().findFragmentByTag("SecondTab");
frag2.displayExchange(s);
}
}
Here is SectionsPagerAdapter.java
package com.example.myapplication.ui.main;
import android.content.Context;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import com.example.myapplication.R;
import java.util.ArrayList;
import java.util.List;
/**
* A [FragmentPagerAdapter] that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragmentList = new ArrayList<>();
private final List<String> stringList = new ArrayList<>();
public void addFragment(Fragment fragment, String title){
fragmentList.add(fragment);
stringList.add(title);
}
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a (defined as a static inner class below).
return fragmentList.get(position);
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return stringList.get(position);
}
#Override
public int getCount() {
// Show 2 total pages.
return fragmentList.size();
}
}
Here is Frag1.java:
package com.example.myapplication;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
public class Frag1 extends Fragment{
private static final String TAG = "FirstTab";
private Button transfer;
private Exchange ex;
public interface Exchange{
public void stringExchange(String s);
}
#Nullable
#Override
public View onCreateView(#NonNull final LayoutInflater inflater, #Nullable final ViewGroup container, #Nullable Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.tab1_fragment, container, false);
transfer = (Button) view.findViewById(R.id.button2);
ex = (Exchange) getActivity();
transfer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String s = "Test";
ex.stringExchange(s);
}
});
return view;
}
}
With its xlm tab1_fragment.xlm:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:id="#+id/tab1"
>
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/transfer"
android:layout_centerInParent="true"/>
</RelativeLayout>
And finally here is the Frag2.java:
package com.example.myapplication;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import java.util.ArrayList;
public class Frag2 extends Fragment {
private static final String TAG = "SecondTab";
private ListView listView;
private ArrayList<String> arrayList = new ArrayList<>();
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tab2_fragment, container, false);
listView = (ListView) view.findViewById(R.id.list_view);
ArrayAdapter arrayAdapter = new ArrayAdapter(getContext(),android.R.layout.simple_list_item_1,arrayList);
listView.setAdapter(arrayAdapter);
return view;
}
public void displayExchange(String s){
arrayList.add(s);
}
}
I think the problem is in MainActivity when I call findFragmentByTag("SecondTab") because it's tag is not set to SecondTab but i don't know how to set it.
Any help will be apreciated!
Use ViewModel to share data between fragments. Refer: https://developer.android.com/topic/libraries/architecture/viewmodel.html#sharing

why method getBackStackEntryCount always return 0

I need to count my fragment, I used getbackstackentrycount, but it always return 0. Can someone tell me whats wrong with my code?
here my code MainActivity.java
package com.example.bams.taskagain;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.example.bams.taskagain.Fragment.FragmentOne;
public class MainActivity extends AppCompatActivity {
Button btn;
FragmentManager fm = getFragmentManager();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.fragOne);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fm.beginTransaction().add(R.id.content, new FragmentOne()).addToBackStack("aa").commit();
//Toast.makeText(getBaseContext(), "text", Toast.LENGTH_LONG).show();
}
});
}
}
and here is my fragment class
package com.example.bams.taskagain.Fragment;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.bams.taskagain.R;
/**
* Created by jack on 25/02/2017.
*/
public class FragmentOne extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("Total back stack "+ ((AppCompatActivity)getActivity()).getSupportFragmentManager().getBackStackEntryCount());
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_one,container,false);
return rootView;
}
}
can someone help me with my code?
I just want to get the BackStack count that my fragement has.
You're using android.app.Fragment and android.app.FragmentManager but using getSupportFragmentManager() to get back stack entry count.
Use
getFragmentManager().getBackStackEntryCount()
getFragmentManager() is used if your fragment is android.app.Fragment and getSupportFragmentManager() if your fragment is android.support.v4.fragment.
For more info on these fragments, take a look at Difference between android.app.Fragment and android.support.v4.app.Fragment

using bitmap with custom spinner

I used this tutorial to make a custom spinner but now I'm having a java.lang.OutOfMemoryError: Failed to allocate a 95976012 byte allocation with 16777120 free bytes and 31MB until OOMerror. I am aware that I should use bitmaps I just don't know how to include the bitmapFactory in my CustomAdapter. I have already compressed my images to sizes less than 16kb and put them in the mipmap folder because they are icons. I have also already tried
<application
android:largeHeap="true"
</application>
Here's my code :
MainActivity.java
package com.kathure.flags;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.Toast;
import static android.R.attr.id;
import static android.graphics.BitmapFactory.*;
import static java.security.AccessController.getContext;
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
String[] countryNames= {
"Kenya" , "Malawi", "Nigeria", "Rwanda", "Tanzania", "Uganda"
};
int [] flags = {
R.mipmap.kenyamin,R.mipmap.malawimin, R.mipmap.nigeriamin, R.mipmap.rwandamin, R.mipmap.tanzaniamin, R.mipmap.ugandamin
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//Getting the instance of Spinner and applying OnItemSelectedListener on it
Spinner spin = (Spinner) findViewById(R.id.simpleSpinner);
spin.setOnItemSelectedListener(this);
CustomAdapter customAdapter=new CustomAdapter(getApplicationContext(),flags,countryNames);
spin.setAdapter(customAdapter);
}
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(getApplicationContext(), countryNames[i], Toast.LENGTH_LONG).show();
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
}
CustomAdapter.java
package com.kathure.flags;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
/**
* Created by kathure on 28/09/16.
*/
public class CustomAdapter extends BaseAdapter {
Context context;
int flags[];
String[] countryNames;
LayoutInflater inflter;
public CustomAdapter(Context applicationContext, int[] flags, String[] countryNames) {
this.context = applicationContext;
this.flags = flags;
this.countryNames = countryNames;
inflter = (LayoutInflater.from(applicationContext));
}
#Override
public int getCount() {
return flags.length;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = inflter.inflate(R.layout.custom_spinner_items, null);
ImageView icon = (ImageView) view.findViewById(R.id.imageView);
TextView names = (TextView) view.findViewById(R.id.textView);
icon.setImageResource(flags[i]);
names.setText(countryNames[i]);
return view;
}
}

Passing values between fragments while using viewpager in android

I want to create a sign up form where the form has been divided into three fragments.There is a next button in the fragment which causes the viewpager to move to the next fragment.But i want to pass values between the fragments how do i do that?
The main class:
package pl.looksok.viewpagerdemo;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
public class MainActivity extends FragmentActivity {
ViewPager pager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyPagerAdapter pageAdapter = new MyPagerAdapter(getSupportFragmentManager());
pager = (ViewPager)findViewById(R.id.myViewPager);
pager.setAdapter(pageAdapter);
}
public void selectFragment(int position){
pager.setCurrentItem(position, true);
// true is to animate the transaction
}
}
The first fragment:
package pl.looksok.viewpagerdemo;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
public class FragmentBlue extends Fragment {
Button btnnext1;
RelativeLayout frag1;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blue, container, false);
btnnext1=(Button) view.findViewById(R.id.btnnext1);
frag1=(RelativeLayout) view.findViewById(R.id.frag1);
btnnext1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
((MainActivity)getActivity()).selectFragment(1);
}
});
return view;
}
}
The second fragment:
package pl.looksok.viewpagerdemo;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
public class FragmentGreen extends Fragment {
Button btnnext2;
RelativeLayout frag2;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_green, container, false);
btnnext2=(Button) view.findViewById(R.id.btnnext2);
frag2=(RelativeLayout) view.findViewById(R.id.frag2);
btnnext2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
((MainActivity)getActivity()).selectFragment(2);
}
});
return view;
}
}
The third fragment:
package pl.looksok.viewpagerdemo;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.support.v4.app.Fragment;
public class FragmentPink extends Fragment {
Button btnnext3;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pink, container, false);
btnnext3=(Button) view.findViewById(R.id.btnnext3);
btnnext3.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
return view;
}
}
I would place a submit button in the last fragment which would post data to the server,So the data in the first two fragments should be available in the last fragment.So i want to know how to pass data from the first two fragments to the last one?
Also is my approach a bad way of achieving the task?Would i be better of creating three different activities and using intent and bundle to pass data?
You can use SharedPreferences. Before you change the fragment save entered values:
SharedPreferences sp = getSharedPreferences("pref_name", MODE_PRIVATE);
SharedPreferences.Editor editor = mSharedPref.edit();
editor.putString("key", value);
editor.commit();
And in other fragment when you want to use saved value:
SharedPreferences sp = getSharedPreferences(MainActivity.PREF_NAME, MODE_PRIVATE);
String value = mSharedPref.getString("key", null);
if(value !=null){
//do something with value
}
Another approach is using interface-callback pattern. You can read more here.

Android Scrollable Tabs + Swipe state when swiping

I'm trying to make an application with multiple Tabs. For each tab I'm using different fragments. And when I leaf through tabs the information in them is changing.
How can I save the state of each tab when swiping?
Code for example:
MainActivity.java:
package com.tabs.example;
import java.util.Locale;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.PagerTabStrip;
import android.support.v4.view.ViewPager;
public class MainActivity extends FragmentActivity {
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
PagerTabStrip pagerTabStrip = (PagerTabStrip) findViewById(R.id.pager_tab_strip);
pagerTabStrip.setBackgroundColor(Color.BLACK);
pagerTabStrip.setTabIndicatorColor(Color.CYAN);
pagerTabStrip.setTextColor(Color.WHITE);
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fragment;
switch (position) {
case 0:
fragment = new Fragment1();
break;
case 1:
fragment = new Fragment2();
break;
case 2:
fragment = new Fragment3();
break;
default:
fragment = null;
break;
}
return fragment;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
}
Fragment1.java:
package com.tabs.example;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Fragment1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment1, container, false);
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
Date date = new Date();
String time = dateFormat.format(date);
TextView tv1 = (TextView) root.findViewById(R.id.tv1);
tv1.setText(time);
return root;
}
}
Fragment2.java:
package com.tabs.example;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Fragment2 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment2, container, false);
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
Date date = new Date();
String time = dateFormat.format(date);
TextView tv2 = (TextView) root.findViewById(R.id.tv2);
tv2.setText(time);
return root;
}
}
Fragment3.java:
package com.tabs.example;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Fragment3 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment3, container, false);
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
Date date = new Date();
String time = dateFormat.format(date);
TextView tv3 = (TextView) root.findViewById(R.id.tv3);
tv1.setText(time);
return root;
}
}
You can cache them all by setting the ViewPagerAdapter like this:
mViewPager.setOffscreenPageLimit(3);

Categories

Resources