I have a variable in MainActivity that I have successfully passed to StoriesActivity.
The problem is with getting it from there to StoriesFragment, which is a TabLayout tab.
I understand about Intents and Bundles but I'm not sure how they'd work in this instance.
This is StoriesActivity:
public class StoriesActivity extends AppCompatActivity {
//This is our tablayout
private TabLayout tabLayout;
//This is our viewPager
private ViewPager viewPager;
private Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stories);
/* +++ START Intent +++ */
Bundle extras = getIntent().getExtras();
final int authorID = extras.getInt("author_id");
final String authorName = extras.getString("author_name");
Log.i("click", Integer.toString(authorID));
// this is successful
/* +++ END Intent +++ */
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle(authorName);
setSupportActionBar(toolbar);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new StoriesFragment(), "Stories");
adapter.addFragment(new CollectionsFragment(), "Collections");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
And this is StoriesFragment (which doesn't work at the moment because it's not accessing the authorID variable from StoriesActivity):
public class StoriesFragment extends Fragment {
public StoriesFragment() {
// Required empty public constructor
}
private ListView storiesListView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// link ListView object with XML ListView
storiesListView = (ListView) findViewById(R.id.stories_list_view);
// create new instance of DatabaseHelper
DatabaseHelper db = new DatabaseHelper(this);
// create list of stories through getAllStories method
List<Book> storyList = db.getAllStories(authorID);
// create new ArrayAdapter
ArrayAdapter<Book> arrayAdapter =
new ArrayAdapter<Book>(this, android.R.layout.simple_list_item_1, storyList);
// link ListView and ArrayAdapter
storiesListView.setAdapter(arrayAdapter);
Log.i("test", storyList.toString());
storiesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Book story = (Book) storiesListView.getItemAtPosition(i);
//Log.i("click", story);
Intent intent = new Intent(StoriesActivity.this, StoryBodyActivity.class);
intent.putExtra("story", story.getTitle());
startActivity(intent);
//Log.i("click", "That's a click!");
}
});
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_stories, container, false);
}
}
StoriesTabsAdapter:
public class StoriesTabsAdapter extends FragmentPagerAdapter {
int mNumOfTabs;
public StoriesTabsAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
private String[] tabTitles = new String[]{"Stories", "Collections"};
// overriding getPageTitle()
#Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
StoriesFragment tab1 = new StoriesFragment();
return tab1;
case 1:
CollectionsFragment tab2 = new CollectionsFragment();
return tab2;
default:
return null;
}
}
#Override
public int getCount() {
return tabTitles.length;
}
}
Here is solution to your problem:
This is your activity:
public class StoriesActivity extends AppCompatActivity {
//This is our tablayout
private TabLayout tabLayout;
//This is our viewPager
private ViewPager viewPager;
private Toolbar toolbar;
private int authorID;
private String authorName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stories);
/* +++ START Intent +++ */
Bundle extras = getIntent().getExtras();
authorID = extras.getInt("author_id");
authorName = extras.getString("author_name");
Log.i("click", Integer.toString(authorID));
// this is successful
/* +++ END Intent +++ */
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle(authorName);
setSupportActionBar(toolbar);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(StoriesFragment.newInstance(authorID, authorName), "Stories");
adapter.addFragment(new CollectionsFragment(), "Collections");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
This is your fragment:
public class StoriesFragment extends Fragment {
private int authorID;
private String authorName;
public StoriesFragment() {
// Required empty public constructor
}
public static StoriesFragment newInstance(int authorID, String authorName) {
Bundle args = new Bundle();
args.putInt("author_id", authorID);
args.putString("author_name", authorName);
StoriesFragment fragment = new StoriesFragment();
fragment.setArguments(args);
return fragment;
}
private ListView storiesListView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Here is your arguments
authorID = getArguments().getInt("author_id");
authorName = getArguments().getString("author_name");
// link ListView object with XML ListView
storiesListView = (ListView) findViewById(R.id.stories_list_view);
// create new instance of DatabaseHelper
DatabaseHelper db = new DatabaseHelper(this);
// create list of stories through getAllStories method
List<Book> storyList = db.getAllStories(authorID);
// create new ArrayAdapter
ArrayAdapter<Book> arrayAdapter =
new ArrayAdapter<Book>(this, android.R.layout.simple_list_item_1, storyList);
// link ListView and ArrayAdapter
storiesListView.setAdapter(arrayAdapter);
Log.i("test", storyList.toString());
storiesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Book story = (Book) storiesListView.getItemAtPosition(i);
//Log.i("click", story);
Intent intent = new Intent(StoriesActivity.this, StoryBodyActivity.class);
intent.putExtra("story", story.getTitle());
startActivity(intent);
//Log.i("click", "That's a click!");
}
});
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_stories, container, false);
}
}
Hope it will help you.
for sending bundle data from your StoriesActivity
private void setupViewPager(ViewPager viewPager) {
Bundle bundle = new Bundle();
bundle.putString("your_key", "yourdata");
// set Fragmentclass Arguments
StoriesFragment fragStory = new StoriesFragment();
fragStory.setArguments(bundle);
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(fragStory, "Stories");
adapter.addFragment(new CollectionsFragment(), "Collections");
viewPager.setAdapter(adapter);
}
Related
I am trying to implement a sales app with 3 stages, whereby a user first adds the items, views the cart to checkout and prints a receipt. The first stage is done and works well. I am implementing this using one Activity with a tabbed layout and 3 fragments for each of the tabs.
On the activity for viewing the cart, I am using a RecyclerView which loads well when the activity is created, but once I add an item and try to view the list, there is no update. However, when I print the item list, the item has been added.
I have tried to update the RecyclerView using notifyDataSetChanged() but it gives me a null pointer exception. I have and tried several solutions but none has worked. Kindly assist.
Below is my code.
NewSaleActivity.java
public class NewSaleActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private ActivityNewSaleBinding binding;
DrawerLayout drawerLayout;
NavigationView navigationView;
TabLayout tabLayout;
Context context;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityNewSaleBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
Toolbar toolbar = findViewById(R.id.new_sale_toolbar);
toolbar.setTitle(R.string.new_sale);
setSupportActionBar(toolbar);
drawerLayout = findViewById(R.id.new_sale_drawer);
navigationView = findViewById(R.id.new_sale_navigation);
navigationView.bringToFront();
navigationView.setNavigationItemSelectedListener(this);
navigationView.setCheckedItem(R.id.nav_sale);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawerLayout.addDrawerListener(toggle);
toggle.setDrawerIndicatorEnabled(true);
toggle.syncState();
context = getApplicationContext();
tabLayout = findViewById(R.id.tab_layout);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
viewPager = binding.viewPager;
viewPager.setAdapter(sectionsPagerAdapter);
viewPager.setOffscreenPageLimit(1);
TabLayout tabs = binding.tabLayout;
tabs.setupWithViewPager(viewPager);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
//When cart tab is selected
if(tab.getPosition() == 1) {
CartFragment cartFragment = new CartFragment();
cartFragment.loadItemsInCart();
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_home:
Intent mainIntent = new Intent(NewSaleActivity.this, MainActivity.class);
startActivity(mainIntent);
finish();
break;
case R.id.nav_inventory:
Intent inventoryIntent = new Intent(NewSaleActivity.this, InventoryActivity.class);
startActivity(inventoryIntent);
finish();
break;
case R.id.nav_sale:
break;
case R.id.nav_logout:
UserLogout.userLogout(NewSaleActivity.this);
break;
}
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
}
CartFragment.java
public class CartFragment extends Fragment {
RecyclerView cartRecyclerView;
TextInputLayout grossTotalInput, discountInput, netTotalInput;
Button checkoutButton;
CartItemAdapter cartItemAdapter;
ArrayList<CartItem> cartItemList;
public CartFragment() {
// Required empty public constructor
}
public static CartFragment newInstance() {
CartFragment fragment = new CartFragment();
Bundle args = new Bundle();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
cartRecyclerView = view.findViewById(R.id.cart_recycler_view);
grossTotalInput = view.findViewById(R.id.gross_total_input);
discountInput = view.findViewById(R.id.discount_input);
netTotalInput = view.findViewById(R.id.net_total_input);
checkoutButton = view.findViewById(R.id.checkout_button);
Paper.init(requireContext());
cartItemList = Paper.book().read("cartItems", new ArrayList<CartItem>());
cartRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
cartItemAdapter = new CartItemAdapter(cartItemList);
cartRecyclerView.setAdapter(cartItemAdapter);
checkoutButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
checkoutOrder();
}
});
cartItemAdapter.notifyDataSetChanged();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_cart, container, false);
}
public void loadItemsInCart() {
ArrayList<CartItem> cartList = Paper.book().read("cartItems", new ArrayList<CartItem>());
for(CartItem cartItem : cartList) {
Log.d("cartItem", cartItem.getItemName());
}
cartItemAdapter.updateCartList(cartList);
Log.d("loadItemsInCart", "Load Items In Cart is triggered");
}
CartItemAdapter.java
public class CartItemAdapter extends RecyclerView.Adapter<CartItemAdapter.ViewHolder> {
private final ArrayList<CartItem> cartItems;
public CartItemAdapter(ArrayList<CartItem> cartItems) {
this.cartItems = cartItems;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView itemCode, itemName, quantity, price;
public ViewHolder(View itemView) {
super(itemView);
this.itemCode = itemView.findViewById(R.id.item_code);
this.itemName = itemView.findViewById(R.id.item_name);
this.quantity = itemView.findViewById(R.id.item_quantity);
this.price = itemView.findViewById(R.id.item_price);
}
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View cartListItem = layoutInflater.inflate(R.layout.add_to_cart_item, parent, false);
return new CartItemAdapter.ViewHolder(cartListItem);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.itemCode.setText(cartItems.get(position).getItemCode());
holder.itemName.setText(cartItems.get(position).getItemName());
holder.quantity.setText(cartItems.get(position).getQuantity().toString());
holder.price.setText(cartItems.get(position).getTotalAmount().toString());
}
#Override
public int getItemCount() {
return cartItems.size();
}
#SuppressLint("NotifyDataSetChanged")
public void updateCartList(ArrayList<CartItem> cartList) {
cartItems.clear();
this.cartItems.addAll(cartList);
notifyDataSetChanged();
}
}
The error message that I get is as below
java.lang.NullPointerException: Attempt to invoke virtual method 'void app.project.jsml_sales_app.adapters.CartItemAdapter.updateCartList(java.util.ArrayList)' on a null object reference
at app.project.jsml_sales_app.activities.fragments.CartFragment.loadItemsInCart(CartFragment.java:128)
at app.project.jsml_sales_app.activities.NewSaleActivity$1.onTabSelected(NewSaleActivity.java:78)
at com.google.android.material.tabs.TabLayout.dispatchTabSelected(TabLayout.java:1993)
at com.google.android.material.tabs.TabLayout.selectTab(TabLayout.java:1986)
Problem:
I'm trying to open a custom dialog after pressing a button in my tabbed fragment.
It's seems like my MainActivity activity is sent to the dialog while i want my tabbed fragment(GroupFragment) to be sent so i can change the editText(for now) in this fragment.
Code:
public class GroupFragment extends Fragment implements AddGroupDialog.AddGroupDialogListener {
private Button addGroupButton;
private TextView textViewNoGroups;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_group, container, false);
addGroupButton = view.findViewById(R.id.addGroupButton);
textViewNoGroups = view.findViewById(R.id.textViewNoGroups);
addGroupButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addNewGroupDialog();
}
});
scaleAnimation(addGroupButton);
return view;
}
private void scaleAnimation(View v){
Animator scale = ObjectAnimator.ofPropertyValuesHolder(v,
PropertyValuesHolder.ofFloat(View.SCALE_X, 0, 1.2f, 1),
PropertyValuesHolder.ofFloat(View.SCALE_Y, 0, 1.2f, 1)
);
scale.setDuration(600);
scale.start();
}
private void addNewGroupDialog(){
AddGroupDialog dialog = new AddGroupDialog();
assert getFragmentManager() != null;
dialog.show(getFragmentManager(), "add new group dialog");
}
#Override
public void applyString(String groupName) {
textViewNoGroups.setText(groupName);
}
}
public class AddGroupDialog extends AppCompatDialogFragment {
private EditText editTextGroupName;
private AddGroupDialogListener listener;
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.layout_add_new_group_dialog, null);
builder.setView(view)
.setTitle("")
.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
String groupName = editTextGroupName.getText().toString();
listener.applyString(groupName);
}
});
editTextGroupName = view.findViewById(R.id.editTextGroupName);
return builder.create();
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
try {
listener = (AddGroupDialogListener) context;
} catch (ClassCastException e){
throw new ClassCastException(context.toString() +
"Must implement AddGroupDialogListener");
}
}
public interface AddGroupDialogListener{
void applyString(String groupName);
}
}
public class MainActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
}
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
#StringRes
private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2, R.string.tab_text_3};
private final Context mContext;
public SectionsPagerAdapter(Context context, FragmentManager fm) {
super(fm);
mContext = context;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position){
case 0:
fragment = new GroupFragment();
break;
case 1:
fragment = new AttendanceFragment();
break;
case 2:
fragment = new StatisticsFragment();
break;
}
return fragment;
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return mContext.getResources().getString(TAB_TITLES[position]);
}
#Override
public int getCount() {
return TAB_TITLES.length;
}
}
Error:
java.lang.ClassCastException: com.example.attendencetaker.MainActivity#26602bcMust implement AddGroupDialogListener
I hope my explanation of the problem is clear. Thank you!
Make the activity implement your interfaces and so on and then pass all data to the fragment with an method on the fragment. You will need an reference to actual Fragment that is displayed.
In your fragment add a method similar to this:
public void updateData(String data) {
editText.setText(data);
}
And in the override method of the interface in your activity to this:
#Override
public void update(String data) {
fragment.updateData(data);
}
Update
Use this Adapter instead:
public class SectionTabAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> fragments = new ArrayList<>();
private ArrayList<String> titles = new ArrayList<>();
public SectionTabAdapter(#NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
}
public void addFragment(Fragment fragment, String title) {
fragments.add(fragment);
titles.add(title);
}
#NonNull
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
}
In your activity then do this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SectionsPagerAdapter sectionTabAdapter = new SectionTabAdapter(this, getSupportFragmentManager());
Fragment groupFragment = new GroupFragment();
Fragment attendanceFragment = new AttendanceFragment();
Fragment statisticsFragment = new StatisticsFragment();
sectionTabAdapter.addFragment(groupFragment, context.getString(R.string.title_1);
sectionTabAdapter.addFragment(attendanceFragment, context.getString(R.string.title_2);
sectionTabAdapter.addFragment(statisticsFragment, context.getString(R.string.title_3);
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionTabAdapter);
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
}
I made a quiz application where I display my Question using a Fragment, and using ViewPager. The Question is taken from SQLite, and here I am confused: If I have 10 questions, then I have to use 10 fragments. How can I use 1 Fragment to hold all questions?
Is there an idea for this?
MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private int mFragmentIndex = 0;
private ViewPager viewPager;
private Button back, next;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = findViewById(R.id.view_pager);
setupViewPager(viewPager);
back = findViewById(R.id.buttonBack);
next = findViewById(R.id.buttonNext);
back.setOnClickListener(this);
next.setOnClickListener(this);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new Question1(), "Question1");
adapter.addFrag(new Question2(), "Question2");
adapter.addFrag(new Question3(), "Question3");
viewPager.setOffscreenPageLimit(adapter.getCount());
viewPager.setAdapter(adapter);
}
#Override
public void onClick(View view) {
if (view == back) {
mfragmentIndex--;
viewPager.setCurrentItem(mFragmentIndex);
} else if(view == next) {
mfragmentIndex++;
viewPager.setCurrentItem(mFragmentIndex);
}
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitle = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment,String title){
mFragmentList.add(fragment);
mFragmentTitle.add(title);
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return super.getPageTitle(position);
}
}
}
My Fragment, Question1:
public class Question1 extends Fragment {
private List<Question> questionsList;
private Question currentQuestion;
private TextView txtQuestion, tvNoOfQs;
private RadioButton rbtnA, rbtnB, rbtnC, rbtnD;
private int obtainedScore = 0;
private int questionId = 0;
private int answeredQsNo = 0;
ArrayList<String> myAnsList;
public Question1() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final DBAdapter dbAdapter = new DBAdapter(getContext());
questionsList = dbAdapter.getAllQuestions();
currentQuestion = questionsList.get(questionId);
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_question1, container, false);
final RadioGroup grp = (RadioGroup)view.findViewById(R.id.radioGroup1);
tvNoOfQs = (TextView)view.findViewById(R.id.tvNumberOfQuestions);
txtQuestion = (TextView)view.findViewById(R.id.tvQuestion);
rbtnA = (RadioButton)view.findViewById(R.id.radio0);
rbtnB = (RadioButton)view.findViewById(R.id.radio1);
rbtnC = (RadioButton)view.findViewById(R.id.radio2);
rbtnD = (RadioButton)view.findViewById(R.id.radio3);
setPertanyaan();
myAnsList = new ArrayList<String>();
return view;
}
private void setPertanyaan() {
rbtnA.setChecked(false);
rbtnB.setChecked(false);
rbtnC.setChecked(false);
rbtnD.setChecked(false);
answeredQsNo = questionId+1;
tvNoOfQs.setText(+answeredQsNo+"/"+questionsList.size());
txtQuestion.setText(currentQuestion.getQUESTION());
rbtnA.setText(currentQuestion.getOptionA());
rbtnB.setText(currentQuestion.getOptionB());
rbtnC.setText(currentQuestion.getOptionC());
rbtnD.setText(currentQuestion.getOptionD());
questionId++;
}
}
I'd recommend using the Fragment's arguments to pass in the question ID. You already have an abstraction around a Question -- it appears that the only thing that really changes here is the question ID.
For example, you would have just a QuestionFragment which is responsible for displaying any given Question:
public class QuestionFragment extends Fragment {
private static final String ARG_QUESTION_ID = "question_id";
public static QuestionFragment newInstance(String questionId) {
final QuestionFragment fragment = new QuestionFragment();
final Bundle args = new Bundle();
args.putString(ARG_QUESTION_ID, questionId);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final String questionId = getArguments().getString(questionId);
final DBAdapter dbAdapter = new DBAdapter(getContext());
questionsList = dbAdapter.getAllQuestions();
currentQuestion = questionsList.get(questionId);
// ...
return view;
}
}
Then, when setting up your ViewPager, just provide the question ID to each instance as you create it:
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(QuestionFragment.newInstance(0), "Question1"));
adapter.addFrag(QuestionFragment.newInstance(1), "Question2"));
adapter.addFrag(QuestionFragment.newInstance(2), "Question3"));
viewPager.setOffscreenPageLimit(adapter.getCount());
viewPager.setAdapter(adapter);
}
i have a Fragment(C) with a ViewPager(Adapter) with 2 Fragments(A/B).
When i call the Fragment once time, they load fine.
But when i call the Fragment(C) the secend time, the Fragment A and B dont call the View onCreateView methode and the isnĀ“t loaded.
The Fragment C is called with Fragmetnmanger:
FragmentC fragment = new FragmentC();
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.adressenmdf_detail_container, fragment).addToBackStack(null).commit();
Fragment C
public BelegeDetails(){
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_belege_details, container, false);
//TODO Actionbar noch anpassen
//getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) rootView.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
setupTabIcons();
The Setups from Fragment C
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(this.getFragmentManager());
adapter.addFragment(new BelegeDetails1(),"Details" );
adapter.addFragment(new BelegeDetailsPos(), "Positionen");
viewPager.setAdapter(adapter);
}
private void setupTabIcons() {
tabLayout.getTabAt(1).setIcon(R.drawable.ic_belege);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
The Fragment A BelegDetails1 und the Fragment B BelegDetailsPos are normal Fragment Classes like:
public BelegeDetails1() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState.......
try changing this:
ViewPagerAdapter adapter = new ViewPagerAdapter(this.getFragmentManager());
with:
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
As you are nesting fragments, you need to use getChildFragmentManager() instead of getFragmentManager()
I have three tabs using the implementation below and they perform very well. When tab is changed the proper fragment is load and so on. The problem is that, when i get to the last tab and comeback to the first fragment, its like its oncreateview method is always triggered again running the other codes it in causing duplicates. Any help will be greatly appreciated.
//Activity on the tab is based
public class Dashboard extends AppCompatActivity {
private TabLayout tabLayout;
private ViewPager viewPager;
private MyViewPagerAdapter myViewPagerAdapter;
private int[] tabIcon = {R.drawable.ic_home, R.drawable.ic_message, R.drawable.ic_person};
android.support.v7.widget.Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dashboard);
//Toolbar
toolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//ViewPager
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
//Tablayout
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
tabLayout.getTabAt(0).setIcon(tabIcon[0]);
tabLayout.getTabAt(1).setIcon(tabIcon[1]);
tabLayout.getTabAt(2).setIcon(tabIcon[2]);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
switch(tab.getPosition()) {
case 0:
viewPager.setCurrentItem(0);
toolbar.setTitle("Home");
break;
case 1:
viewPager.setCurrentItem(1);
toolbar.setTitle("Messages");
break;
case 2:
viewPager.setCurrentItem(2);
toolbar.setTitle("Profile");
break;
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
private void setupViewPager(ViewPager viewPager){
myViewPagerAdapter = new MyViewPagerAdapter(getSupportFragmentManager());
myViewPagerAdapter.addFragments(new CategoryFragment(), "Categories");
myViewPagerAdapter.addFragments(new MessagesFragment(), "Messages");
myViewPagerAdapter.addFragments(new ProfileFragment(), "Profile");
viewPager.setAdapter(myViewPagerAdapter);
}
//View Pager Adapter
public class MyViewPagerAdapter extends FragmentPagerAdapter {
ArrayList<Fragment> fragments = new ArrayList<>();
ArrayList<String> tabTitles = new ArrayList<>();
public void addFragments(Fragment fragments, String titles){
this.fragments.add(fragments);
this.tabTitles.add(titles);
}
public MyViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public CharSequence getPageTitle(int position) {
//return tabTitles.get(position);
return null;
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
}
//Main first fragment code
public class CategoryFragment extends Fragment {
private DBHandler dbHandler;
private ListView listView;
private ListAdapter adapter;
ArrayList<Categories> categoriesList = new ArrayList<Categories>();
public CategoryFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home, container, false);
//Setting up the basic categories
dbHandler = new DBHandler(view.getContext());
//Get Categories from database
final Cursor cursor = dbHandler.getCategories(0);
if (cursor != null) {
if(cursor.moveToFirst()){
do{
Categories categories = new Categories();
categories.set_id(cursor.getInt(0));
categories.set_categoryname(cursor.getString(2));
categories.set_categoriescaption(cursor.getString(3));
categoriesList.add(categories);
}while (cursor.moveToNext());
}
cursor.close();
}
listView = (ListView) view.findViewById(R.id.categories);
adapter = new CategoryAdapter(view.getContext(), R.layout.cursor_row, categoriesList);
listView.setAdapter(adapter);
listView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Integer cid = (int) (long) adapter.getItemId(position);
TextView categoryname = (TextView) view.findViewById(R.id.cursor);
String cname = categoryname.getText().toString();
Intent i = new Intent(view.getContext(), CategoryList.class);
i.putExtra("categoryname", cname);
i.putExtra("categoryid", cid);
startActivity(i);
}
}
);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
So when i swipe back here from the last tab. OncreateView runs again. How can i handle that and prevent duplicates. Thank you
By defaults ViewPager retains only 1 page in the view hierarchy in an idle state.So when you swipe to third tab the viepager destroys the first tab in order to retain the second one.
To solve this issue add this line
viewPager.setOffscreenPageLimit(3);
after you set your adapter.
Check here the documentation for more