Passing spinner value from activity to fragment - java

I have a custom spinner with an ArrayList defined in an activity. On selected item a new fragment is created. Can I pass the value of which fragment was created ("Single Massage" or "Couples Massage") to another fragment within the same activity and then from that fragment pass it to another activity and update its textview? This might not be the best approach, but I am a beginner, so I really don't know that much. Here is my code.
Spinner:
public class MassageActivity extends AppCompatActivity {
private Spinner mSpinner;
private Toolbar mToolbar;
private FragmentManager mFragmentManager;
private FragmentTransaction mFragmentTransaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_massage);
mToolbar = (Toolbar) findViewById(R.id.toolbar_massage);
setSupportActionBar(mToolbar);
ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setDisplayHomeAsUpEnabled(true);
}
if (ab != null) {
ab.setDisplayShowTitleEnabled(false);
}
customSpinner();
mFragmentManager = getSupportFragmentManager();
}private void customSpinner() {
final ArrayList<String> massageType = new ArrayList<>();
massageType.add("Single Massage");
massageType.add("Couples Massage");
massageType.add("Pamper Party");
mSpinner = (Spinner) findViewById(R.id.spinner);
CustomSpinnerAdapter spinnerAdapter = new CustomSpinnerAdapter(getApplicationContext(), massageType);
mSpinner.setAdapter(spinnerAdapter);
mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (parent.getItemAtPosition(position).toString()
.equals("Pamper Party")) {
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.fragment_container_massage,
new PamperPartyFragment()).commit();
}
if (parent.getItemAtPosition(position).toString()
.equals("Single Massage")) {
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.fragment_container_massage,
new SingleMassageFragment()).commit();
}
if (parent.getItemAtPosition(position).toString()
.equals("Couples Massage")){
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.fragment_container_massage,
new CouplesMassageFragment()).commit();
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}}
EDIT:
I followed the and done this:
String spinnerValue = mSpinner.getSelectedItem().toString();
Intent i = new Intent(this, SingleMassageFragment.class);
i.putExtra("spinnerValue", spinnerValue);
setIntent(i);
And then in my fragment:
MassageActivity activity = (MassageActivity) getActivity();
Intent f = activity.getIntent();
String spinnerValue = f.getStringExtra("spinnerValue");
Utils.doToast(getContext(), spinnerValue);
But whichever fragment I selected, I always get the same toast "Single Massage". Why is that? For any case here's my adapter:
public class CustomSpinnerAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> mMassageType;
private LayoutInflater mInflater;
private TextView tvSpinner;
public CustomSpinnerAdapter(Context context, ArrayList<String> massageType) {
mContext = context;
mMassageType = massageType;
mInflater = (LayoutInflater.from(context));
}
#Override
public int getCount() {
return mMassageType.size();
}
#Override
public Object getItem(int position) {
return mMassageType.get(position);
}
#Override
public long getItemId(int position) {
return (long) position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(R.layout.spinner_layout, null);
tvSpinner = (TextView) convertView.findViewById(R.id.tvSpinner);
tvSpinner.setText(mMassageType.get(position));
return convertView;
}
}

To Pass Data
PamperPartyFragment mPamperPartyFragment = new PamperPartyFragment();
Bundle bundle = new Bundle();
bundle.putInt(key, value);
mPamperPartyFragment.setArguments(bundle);
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.fragment_container_massage,
mPamperPartyFragment ).commit();
For Getting data in fragment
Bundle bundle = this.getArguments();
int myInt = bundle.getInt(key, defaultValue);
try This in your spinner setOnItemSelectedListener to send data
Bundle bundle = new Bundle();
bundle.putString("spinnerValue",parent.getItemAtPosition(position).toString());
mPamperPartyFragment.setArguments(bundle);
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.fragment_container_massage,
mPamperPartyFragment ).commit();
to read data in your fragment add this in your onCreate
Bundle bundle = getArguments();
String selectedVAlue = bundle.getString("spinnerValue");

in activity :
Intent i = new Intent (this, fragmentname.class);
i.putInt(key, value);
setIntent(i);
in fragment :
ActivityName activity = (ActivityName) getActivity();
Intent f= activity.getIntent();
int yrid = f.getIntExtra(key);

Related

Fragment has not been attached yet for Nested fragment

I'm trying to display the bottom dialog fragment (AddNewHabit.java) when user clicked an item from the RecyclerView, but I kept getting the error that the fragment has not been attached yet. I don't know where or how should I attach it to make bottomSheetDialogFragment.show() work.
Logcat:
2022-09-11 20:52:31.916 21228-21228/com.unicode.android.wodehabit E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.unicode.android.wodehabit, PID: 21228
java.lang.IllegalStateException: Fragment AddNewHabit{fdd5021} (ce46aa77-b5b3-43e6-9564-559dd68d8ad9) has not been attached yet.
at androidx.fragment.app.Fragment.getChildFragmentManager(Fragment.java:1075)
at com.unicode.android.wodehabit.HabitsAdapter.editHabit(HabitsAdapter.java:91)
at com.unicode.android.wodehabit.HabitsAdapter$1.onClick(HabitsAdapter.java:50)
at android.view.View.performClick(View.java:7448)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28305)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Here's HabitsFragment:
public class HabitsFragment extends Fragment implements DialogCloseListener{
private List<HabitModel> mHabitList;
private RecyclerView mRecyclerView;
private HabitsAdapter mHabitsAdapter;
private ImageButton mAddTaskBtn;
private Spinner mDropdown;
private DataBaseHandler db;
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public HabitsFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment HabitsFragment.
*/
// TODO: Rename and change types and number of parameters
public static HabitsFragment newInstance(String param1, String param2) {
HabitsFragment fragment = new HabitsFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_habits, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
db = new DataBaseHandler(getActivity());
db.openDatabase();
mAddTaskBtn = (ImageButton) view.findViewById(R.id.add_new_habit_btn);
mAddTaskBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AddNewHabit.newInstance().show(getChildFragmentManager(), AddNewHabit.TAG);
}
});
mRecyclerView = (RecyclerView) view.findViewById(R.id.habit_recyclerview);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mHabitsAdapter = new HabitsAdapter(db, getActivity());
mRecyclerView.setAdapter(mHabitsAdapter);
updateRecyclerView();
}
public void handleDialogClose(DialogInterface dialog){
updateRecyclerView();
}
public void updateRecyclerView(){
mHabitList = db.getAllHabits();
Collections.reverse(mHabitList);
mHabitsAdapter.setHabit(mHabitList);
mHabitsAdapter.notifyDataSetChanged();
}
}
AddNewHabit.java:
public class AddNewHabit extends BottomSheetDialogFragment {
public static final String TAG = "com.unicode.android.wodehabit.action_bottom_dialog";
private EditText cueTxt, habitTxt, descriptionTxt;
private Button cancelBtn, addBtn;
private Spinner dropdown;
private DataBaseHandler db;
public static AddNewHabit newInstance() {
return new AddNewHabit();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NORMAL, R.style.DialogStyle);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.new_habit, container, false);
//readjust bottom sheet dialog and move upward when we type something
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
return view;
}
//Define codes needed to execute functions in dialog fragment
#Override
public void onViewCreated(View view, Bundle saveInstanceState) {
super.onViewCreated(view, saveInstanceState);
cueTxt = (EditText) getView().findViewById(R.id.new_task_cue);
habitTxt = (EditText) getView().findViewById(R.id.new_task_habit);
descriptionTxt = (EditText) getView().findViewById(R.id.new_task_description);
dropdown = (Spinner) getView().findViewById(R.id.new_task_preposition);
cancelBtn = (Button) getView().findViewById(R.id.cancel_habit_button);
addBtn = (Button) getView().findViewById(R.id.add_habit_button);
//Spinner adapter
String[] items = new String[]{"before", "during", "after"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
dropdown.setAdapter(adapter);
boolean isUpdate = false;
final Bundle bundle = getArguments();
if (bundle != null) {
isUpdate = true;
String cue = bundle.getString("cue");
cueTxt.setText(cue);
String habit = bundle.getString("habit");
habitTxt.setText(habit);
String description = bundle.getString("description");
descriptionTxt.setText(description);
}
db = new DataBaseHandler(getActivity());
db.openDatabase();
cancelBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getParentFragmentManager().beginTransaction().remove(AddNewHabit.this).commit();
}
});
//final boolean finalIsUpdate = isUpdate;
boolean finalIsUpdate = isUpdate;
addBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String cue = cueTxt.getText().toString();
String preposition = dropdown.getSelectedItem().toString();
String habit = habitTxt.getText().toString();
String description = descriptionTxt.getText().toString();
String fullHabit = habit + " " + preposition + " " + cue;
if(finalIsUpdate){
db.updateHabit(bundle.getInt("id"), habit, description);
}else{
if (cue.isEmpty() || habit.isEmpty()) {
Toast.makeText(getActivity(), R.string.complete_toast, Toast.LENGTH_LONG).show();
} else {
HabitModel habit1 = new HabitModel();
habit1.setTitle(fullHabit);
habit1.setDescription(description);
db.insertHabit(habit1);
}
}
dismiss();
}
});
}
#Override
public void onDismiss(DialogInterface dialog){
Activity activity = getActivity();
if(activity instanceof DialogCloseListener){
((DialogCloseListener)activity).handleDialogClose(dialog);
}
}
}
Here's HabitsAdapter.java:
public class HabitsAdapter extends RecyclerView.Adapter<HabitsAdapter.ViewHolder> {
private List<HabitModel> mHabitList;
private Activity mActivity;
private DataBaseHandler db;
public HabitsAdapter(DataBaseHandler db, Activity activity){
this.db = db;
this.mActivity = activity;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.habit_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
db.openDatabase();
HabitModel item = mHabitList.get(position);
holder.mTitle.setText(item.getTitle());
holder.mDescription.setText(item.getDescription());
int pos = holder.getAdapterPosition();
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
editHabit(pos);
}
});
}
#Override
public int getItemCount() {
return mHabitList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
TextView mTitle, mDescription;
FloatingActionButton mFab;
ViewHolder(View view){
super(view);
mTitle = (TextView) view.findViewById(R.id.habit_title);
mDescription = (TextView) view.findViewById(R.id.habit_description);
mFab = (FloatingActionButton) view.findViewById(R.id.check_off_button);
}
}
public void setHabit(List<HabitModel> habitList){
this.mHabitList = habitList;
notifyDataSetChanged();
}
public Context getContext(){
return mActivity;
}
public void editHabit(int position){
HabitModel habit = mHabitList.get(position);
Bundle bundle = new Bundle();
bundle.putInt("id", habit.getId());
bundle.putString("habit", habit.getTitle());
bundle.putString("description", habit.getDescription());
AddNewHabit fragment = new AddNewHabit();
fragment.setArguments(bundle);
//THE PROBLEM
fragment.show(fragment.getChildFragmentManager(), AddNewHabit.TAG);
}
public void deleteHabit(int position){
HabitModel habit = mHabitList.get(position);
db.deleteHabit(habit.getId());
mHabitList.remove(position);
notifyItemRemoved(position);
}
}
Found the answer from https://stackoverflow.com/a/22971406/15433004
Replaced this code in HabitsAdapter:
AddNewHabit fragment = new AddNewHabit();
fragment.setArguments(bundle);
fragment.show(fragment.getChildFragmentManager(), AddNewHabit.TAG);
To:
FragmentActivity activity = (FragmentActivity)(getContext());
FragmentManager fm = activity.getSupportFragmentManager();
AddNewHabit fragment = new AddNewHabit();
fragment.setArguments(bundle);
fragment.show(fm, AddNewHabit.TAG);

Strange behavior of OnItemClickListener inside RecyclerView inside Fragment

Need help with android app (java)
My app starts with SplashActivity. During it I`m getting json via retrofit request and after successfull response I fill my DB
SplashActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
ISplashInteractor splashInteractor = new SplashInteractor();
moviePresenter = new MoviePresenter(this, splashInteractor);
moviePresenter.initDB();
}
after DB successfully loaded automatically starts MovieListActivity
public class MovieListActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_list);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment allMoviesFragment = new AllMoviesFragment();
String tag = "MovieList";
transaction.replace(R.id.main_container, allMoviesFragment, tag);
transaction.commit();
}
}
and at once list of movies loads inside inner fragment AllMoviesFragment(inside recyclerView). till this point everything is ok.
now I set onRecyclerViewItemClickListener - it must open another fragment inside MovieListActivity but instead of this - my app restarts from begining and I observe loading of SpalshActivity again(I put progressbar during request) and again my RecyclerView...
my RecyclerViewAdapter
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private List<MovieDetails> movieList;
private OnRecyclerViewItemClickListener onRecyclerViewItemClickListener;
public RecyclerViewAdapter(List<MovieDetails> movieList) {
this.movieList = movieList;
}
public void setOnRecyclerViewItemClickListener(OnRecyclerViewItemClickListener onRecyclerViewItemClickListener){
this.onRecyclerViewItemClickListener = onRecyclerViewItemClickListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.simple_selectable_list_item, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
MovieDetails movieDetails = (movieList.get(position));
holder.name.setText(movieDetails.getTitle());
holder.year.setText(String.valueOf(movieDetails.getReleaseYear()));
}
#Override
public int getItemCount() {
if (movieList == null)
return 0;
return movieList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView name;
TextView year;
public ViewHolder(View itemView) {
super(itemView);
name = itemView.findViewById(R.id.movie_name);
year = itemView.findViewById(R.id.release_year);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(onRecyclerViewItemClickListener != null){
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION){
onRecyclerViewItemClickListener.onRecyclerViewItemClick(position);
}
}
}
});
}
}
public interface OnRecyclerViewItemClickListener {
void onRecyclerViewItemClick(int position);
}
}
my AllMoviesFragment
public class AllMoviesFragment extends Fragment implements RecyclerViewAdapter.OnRecyclerViewItemClickListener {
private static final String CURR_MOVIE = "Current Movie";
private static final String TAG = "MSApp";
List<MovieDetails> movieList;
RecyclerView recyclerView;
public AllMoviesFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
movieList = App.getAppInstance().getDatabaseInstance().getMovieDao().getAllMovies();
movieList.sort(new Comparator<MovieDetails>() {
#Override
public int compare(MovieDetails o1, MovieDetails o2) {
return o2.getReleaseYear() - o1.getReleaseYear();
}
});
View resultView = inflater.inflate(R.layout.fragment_all_movies, container, false);
recyclerView = resultView.findViewById(R.id.recycler_view);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(movieList);
adapter.setOnRecyclerViewItemClickListener(AllMoviesFragment.this);
recyclerView.setAdapter(adapter);
return resultView;
}
#Override
public void onRecyclerViewItemClick(int position) {
MovieDetails choosenMovie = movieList.get(position);
FragmentManager fragmentManager = getFragmentManager();
Fragment movieDetailsFragment = new MovieDetailsFragment();
Bundle args = new Bundle();
args.putParcelable(CURR_MOVIE, choosenMovie);
movieDetailsFragment.setArguments(args);
String tag = "MovieDetails";
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, movieDetailsFragment, tag);
transaction.addToBackStack(tag);
transaction.commit();
}
}
sorry for long post. I dont know how to cut it
I use App class for db access if it is important
#AkakiKapanadze
you was almost right
I didnot see the error message because it disappeared less 1 second
and class MovieDetailsFragment
after I remove binder of ButterKnife all work... I dont know WHY - I always use Butterknife inside Fragments

Passing data from Fragments to Fragments error

I use a Bundle to pass data between Fragments. However, I ran into some problems. My Bundle is not working, I do not know why. Because I do everything as I did before.
Here is my Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jegyek);
BottomNavigationView bottomNav = findViewById(R.id.lista_navigation);
bottomNav.setOnNavigationItemSelectedListener(navListener);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container_lista,
new Tantargylista()).commit();
}
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.nav_tantargylista:
selectedFragment = new ObjectList();
break;
case R.id.nav_dolgozatlista:
selectedFragment = new ExamList();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container_lista,
selectedFragment).commit();
return true;
}
};
}
My first Fragment:
View v;
DB mydb;
ListView listView;
String teszt;
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
v = inflater.inflate(R.layout.fragment_objectlist, container, false);
listView = (ListView)v.findViewById(R.id.Jegyekview);
mydb = new DB(getActivity());
final ArrayList<String> thelist = new ArrayList<>();
Cursor data = mydb.getTantargynev();
if (data.getCount() == 0) {
Toast.makeText(getActivity(), "Empty", Toast.LENGTH_SHORT).show();
} else {
while (data.moveToNext()) {
thelist.add(data.getString(0));
ListAdapter listadapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, thelist);
listView.setAdapter(listadapter);
}
listView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
teszt = thelist.get(i);
Bundle bundle = new Bundle();
bundle.putString("test", teszt);
Fragment targyAdatok = new targyAdatok();
Fragment jegyekAllando = new jegyekAllando();
jegyekAllando.setArguments(bundle);
FragmentTransaction FragTan = getActivity().getSupportFragmentManager().beginTransaction();
FragTan.replace(R.id.jegyekMenu, targyAdatok);
FragTan.commit();
}
}
});
}
return v;
}
There is a second Fragment which has a Button. If the Button is pressed, then the third Fragment is open.
Button button = (Button)v.findViewById(R.id.elemzes);
elemzes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment jegyekAllando = new jegyekAllando();
FragmentTransaction FragTan2 = getFragmentManager().beginTransaction();
FragTan2.replace(R.id.fragment_container_lista,jegyekAllando);
FragTan2.commit();
}
});
My third Fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_jegyek_allando, container, false);
Bundle bundle = getArguments();
String jegyAtlagSt = bundle.getString("test");
//Here crash the program. :/
return rootView;
}
You have not passed anything from your second Fragment while opening your third Fragment. Hence you need to do something like the following.
Button button = (Button)v.findViewById(R.id.elemzes);
elemzes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment jegyekAllando = new jegyekAllando();
// Get a bundle
Bundle bundle = new Bundle();
bundle.putString("test", teszt);
// Set as argument
jegyekAllando.setArguments(bundle);
// Begin the transaction
FragmentTransaction FragTan2 = getFragmentManager().beginTransaction();
FragTan2.replace(R.id.fragment_container_lista,jegyekAllando);
FragTan2.commit();
}
});
I think the problem is your second fragment is not passing the bundle from the first fragment to the third fragment in this code
Button button = (Button)v.findViewById(R.id.elemzes);
elemzes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment jegyekAllando = new jegyekAllando();
FragmentTransaction FragTan2 = getFragmentManager().beginTransaction();
FragTan2.replace(R.id.fragment_container_lista,jegyekAllando);
FragTan2.commit();
}
});

Can't cast context to CustomCallBack interface in FragmentAdapter of a Fragment

I have problem when I cast the context in the FragmentAdapter of a Fragment. My app process is:
- When I click on navigation list item (Nav One) it will show the fragment with the recyclerview and cardview.
- When I click on the image of cardview list item I want get an action to show the Toast message or do something with a costom interface named (CustomCallBack).
This is my code:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private ListView lvNavigation;
private DrawerLayout mDrawer;
private NavigationView mNavigation;
private LinearLayout llMianContain;
String[] navigation = new String[]{"Nav One","Nav Two", "Nav Three","Nav Four"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
lvNavigation = (ListView) findViewById(R.id.lv_listView);
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
mNavigation= (NavigationView) findViewById(R.id.navigation_view);
llMianContain = (LinearLayout) findViewById(R.id.ll_main_content);
setSupportActionBar(toolbar);
lvNavigation.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, navigation));
lvNavigation.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
replaceFragment(i);
lvNavigation.setItemChecked(i, true);
hideDrawer();
}
});
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mDrawer, toolbar, R.string.open, R.string.close);
mDrawer.setDrawerListener(toggle);
toggle.syncState();
}
private void replaceFragment(int position){
Fragment fragment = null;
switch (position){
case 0:
fragment = new OneFragment();
break;
case 1:
fragment = new TwoFragment();
break;
case 2:
fragment = new ThreeFragment();
break;
case 3:
fragment= new FourFragment();
break;
default:
fragment = new OneFragment();
break;
}
if(null!= fragment){
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.ll_main_content, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
private void hideDrawer(){
mDrawer.closeDrawer(GravityCompat.START);
}
private void showDrawer(){
mDrawer.openDrawer(GravityCompat.START);
}
#Override
public void onBackPressed() {
if (mDrawer.isDrawerOpen(GravityCompat.START))
hideDrawer();
else
super.onBackPressed();
}
}
OneFragment.java
public class OneFragment extends Fragment implements FragmentOneAdapter.CustomCallBack{
private ArrayList<ListItem> listItems;
private RecyclerView recyclerView;
private FragmentOneAdapter adapter;
public OneFragment() { }
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view =inflater.inflate(R.layout.fragment_one, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(manager);
listItems = new ArrayList<>();
for(int i=0;i<40;i++){
listItems.add(new ListItem(R.drawable.ic_account_circle_black_48dp, "MY NAME "+ i));
}
adapter = new FragmentOneAdapter(listItems, getActivity());
recyclerView.setAdapter(adapter);
return view;
}
#Override
public void onProfileClick(int position) {
Toast.makeText(getActivity(), "position "+ position, Toast.LENGTH_SHORT).show();
}
}
FragmentAdapter.java
public class FragmentOneAdapter extends RecyclerView.Adapter<FragmentOneAdapter.FragmentOneViewHolder> {
private ArrayList<ListItem> listItems;
private Context context;
final CustomCallBack customCallBack;
public FragmentOneAdapter(ArrayList<ListItem> listItems, Context context){
this.listItems = listItems;
this.context = context;
this.customCallBack = (CustomCallBack) context;
}
#Override
public FragmentOneViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_one_item, parent,false);
FragmentOneViewHolder holder = new FragmentOneViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(FragmentOneViewHolder holder, int position) {
holder.tvName.setText(listItems.get(position).getName());
holder.ivProfile.setImageResource(listItems.get(position).getProfile());
}
#Override
public int getItemCount() {
return listItems.size();
}
class FragmentOneViewHolder extends RecyclerView.ViewHolder{
TextView tvName;
ImageView ivProfile;
LinearLayout llFooter;
public FragmentOneViewHolder(View itemView) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tv_name);
ivProfile = (ImageView) itemView.findViewById(R.id.iv_profile);
llFooter= (LinearLayout) itemView.findViewById(R.id.ll_footer);
ivProfile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
customCallBack.onProfileClick(getAdapterPosition());
}
});
}
}
// MY Custom CallBack
interface CustomCallBack{
void onProfileClick(int position);
}
}
Hmm,
So your Fragment is implementing CustomCallBack interface
Why don't you just pass the Fragment object itself to the adapter?
for example, in the FragmentOneAdapter.java,
change:
public FragmentOneAdapter(ArrayList<ListItem> listItems, Context context) ===> public FragmentOneAdapter(ArrayList<ListItem> listItems, CustomCallBack callback)
then:
this.customCallBack = (CustomCallBack) context; ===> this.customCallBack = callback;
Obviously, now in OneFragment.java,
just pass 'this' as parameter as the Fragment itself is the CustomCallBack:
adapter = new FragmentOneAdapter(listItems, getActivity()); ===> adapter = new FragmentOneAdapter(listItems, this);

ArrayList<String> getIntent().getStringArrayListExtra

I want to get an ArrayList from one Fragment to another, I use the Intentmethod, like this:
Fragment where I want to get it from
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.putStringArrayListExtra("server_name_list", server_name_list);
If I debug this, I can see the new entry I did. But in the Fragment where I use getIntent().getStringArrayListExtra there is no new entry.
What did I wrong?
Here is the code from the Fragment where I use the method:
/* Server Name Spinner */
ArrayList<String> server_name_list = getIntent().getStringArrayListExtra("server_name_list");
if (server_name_list != null) {
spinner = (Spinner) view.findViewById(R.id.server_spinner);
;
ArrayAdapter<String> server_adapter = new ArrayAdapter<String>(this.getActivity(),
android.R.layout.simple_spinner_item, server_name_list);
server_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(server_adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
selected = parent.getItemAtPosition(pos).toString();
myWebView.loadUrl(selected);
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
Edit: Whole code
public class MainActivity extends AppCompatActivity implements AddServerFragment.Callback {
static WebView myWebView;
Fragment AddServerFragment, WebViewFragment;
ArrayList<String> server_name_list;
#Override
public ArrayList<String> getArrayListFromActivity() {
WebViewFragment frag = (WebViewFragment) getSupportFragmentManager().findFragmentByTag("AddServerFragment");
if (frag != null) {
server_name_list = frag.getArrayListFromWebViewFragment();
}
return server_name_list;
}
/* Menu */
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.webview:
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new WebViewFragment() {
})
.commit();
return true;
case R.id.add_server:
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new AddServerFragment() {
})
.commit();
return true;
case R.id.menu_refresh:
myWebView.reload();
return true;
default:
return true;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.container) != null) {
if (savedInstanceState != null) {
return;
}
AddServerFragment = new Fragment();
WebViewFragment = new Fragment();
}
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new WebViewFragment() {
})
.commit();
}
/*WebView Fragment*/
public class WebViewFragment extends Fragment {
String selected;
Spinner spinner;
public WebViewFragment(){
}
private Callback callback;
public interface Callback {
public ArrayList<String> getArrayListFromActivity();
}
#Override
public void onAttach(Activity activity) {
callback = (Callback) activity;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.webview, container, false);
/* WebView */
myWebView = (WebView) view.findViewById(R.id.webView);
myWebView.setWebViewClient(new WebC());
WebSettings webSettings = myWebView.getSettings();
/* JavaScript Enable */
webSettings.setJavaScriptEnabled(true);
/* Server Name Spinner */
ArrayList<String> server_name_list = callback.getArrayListFromActivity();
if (server_name_list != null) {
spinner = (Spinner) view.findViewById(R.id.server_spinner);
;
ArrayAdapter<String> server_adapter = new ArrayAdapter<String>(this.getActivity(),
android.R.layout.simple_spinner_item, server_name_list);
server_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(server_adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
selected = parent.getItemAtPosition(pos).toString();
myWebView.loadUrl(selected);
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
return view;
}
}
/*Add Server Fragment*/
public class AddServerFragment extends Fragment
implements View.OnClickListener {
#Override
public void onClick(View view) {
}
public AddServerFragment(){
}
Button btn_back, btn_add;
EditText server_ip, server_name;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.add_ip, container, false);
server_ip = (EditText) view.findViewById(R.id.edit_server_address);
server_name = (EditText) view.findViewById(R.id.edit_server_name);
btn_back = (Button) view.findViewById(R.id.btn_back);
btn_back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new WebViewFragment() {
})
.commit();
}
});
btn_add = (Button) view.findViewById(R.id.btn_add);
btn_add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String new_server_ip = null, new_server_name = null;
ArrayList<String> server_name_list = new ArrayList<>();
ArrayList<String> server_ip_list = new ArrayList<>();
new_server_ip = server_ip.getText().toString();
server_ip_list.add(new_server_ip);
new_server_name = server_name.getText().toString();
server_name_list.add(new_server_name);
}
});
return view;
}
}
/* WebView Client */
public class WebC extends WebViewClient {
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
}
}
}
You can store your ArrayList as a member variable of your container activity :
private ArrayList<String> server_name_list;
Add a getter:
public ArrayList<String> getArrayList() {
return server_name_list;
}
And in your fragments, you access it this way: (supposing that the container activity's name is MainActivity)
ArrayList<String> arraylist = ((MainActivity)getActivity()).getArrayList();
JDev's answer is correct in so far as it will give you the result you want with the smallest amount of code. It is also, conceptually, the easiest method to understand. However, the technique recommended by Android Developers for a Fragment to communicate with its hosting Activity is via an interface.
It is worth learning this technique IMO, even if you are unfamiliar with interfaces in Java and Android. This is because interfaces are used in all but the most basic of projects, and they underpin many recommended design patterns, so you can be sure they will turn up sooner or later :)
Here is how you would solve your problem with an interface:
public class MyFragment extends Fragment {
private Callback callback;
public interface Callback {
public ArrayList<String> getArrayListFromActivity();
}
#Override
public void onAttach(Activity activity) {
callback = (Callback) activity;
//NB: The above will throw ClassCastException if your Activity
//Does not implement MyFragment.Callback
}
//Later in your code, whenever you want to grab the ArrayList<String> from your Activity:
ArrayList<String> arrList = callback.getArrayListFromActivity();
Inside MainActivity:
public class MainActivity extends AppCompatActivity implements MyFragment.Callback {
ArrayList<String> arrayList;
#Override
public ArrayList<String> getArrayListFromActivity() {
//If the ArrayList is in your Activity, then use:
return arrayList;
//If the ArrayList is in another Fragment, then use:
FragmentTwo frag = (FragmentTwo) getSupportFragmentManager().findFragmentByTag("tag_of_fragment_two");
if (frag != null) {
arrayList = frag.getArrayListFromFragmentTwo();
return arrayList;
}
}
}
ArrayList<String> server_name_list;//declare variable
... void onCreate(...)
{
.
.
.
server_name_list = getIntent().getStringArrayListExtra("server_name_list");//assign value
}
try this.if doesn't work try
intent.putExtra("server_name_list", server_name_list);
instead of
intent.putStringArrayListExtra("server_name_list", server_name_list);
you can simply pass any parameter through static instance of that fragment.
intent is normally used to transfer data among activities not fragments
DestinationFragment Frag = DestinationFragment.getInstance(yourArrayList);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (shouldAddToBackStack)
ft.addToBackStack(tag);
else {
getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
ft.replace(R.id.container, Frag, tag)
.commit();
getSupportFragmentManager().executePendingTransactions();
in your DestinationFragment
public static DestinationFragment getInstance(ArrayList yourArrayList){
DestinationFragment fragment=new DestinationFragment();
Bundle args = new Bundle();
args.putString(args, yourArrayList);
fragment.setArguments(args);
return fragment;
}

Categories