I want to pass itemId from main activity to another activity.
Now i wrote code like below, But i dont want like this, Just i want pass itemId from this activity to another when option is selected. In another activity i will write switch case option.
Here my code:
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch(item.getItemId()) {
case android.R.id.home:mDrawerToggle.onOptionsItemSelected(item);
case R.id.action_settings:SettingsFragment fragmentS = new SettingsFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, fragmentS).commit();
break;
}
return super.onOptionsItemSelected(item);
}
Use Intents to pass data between activities.
Intent intent = new Intent(current.this, Next.class);
intent.putExtra("itemid", item.getItemId());
startActivity(intent);
And in the other activity.
String itemId= getIntent().getStringExtra("itemid");
switch(itemId)
{
...
}
From your code it seems you want to pass value from a fragment to another fragment. If so you should edit the question. Its saying you want to pass value from one activity to another. I am answering according to fragment.
Do this
switch(item.getItemId()) {
case android.R.id.home:
mDrawerToggle.onOptionsItemSelected(item);
case R.id.action_settings:
SettingsFragment fragmentS = new SettingsFragment();
Bundle args = new Bundle();
args.putInt("ItemID", item.getItemId());
fragmentS.setArguments(args);
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, fragmentS).commit();
break;
}
In other fragment get the value like this
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
int itemId = getArguments().getInt("ItemID");
return inflater.inflate(R.layout.fragment, container, false);
}
So, you want to pass data to a fragment actually?
Try adding before strating a fragment transaction:
Bundle bundle = new Bundle();
bundle.putInt("id", tem.getItemId());
fragmentS.setArguments(bundle);
Related
I am using a fragment to hold 4 card views, which should start a new activity on click. It can display the toast I generate which shows that the click function is working but it is unable to activate the intent.
I have tried using several names for the activity and also
Intent intent = new Intent (getActivity(), activity name.class)
code to start activity
package com.example.eb.ui.home;
import ...
public class HomeFragment extends Fragment implements View.OnClickListener{
private HomeViewModel homeViewModel;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
homeViewModel = ViewModelProviders.of(this).get(HomeViewModel.class);
View root = inflater.inflate(R.layout.fragment_home, container, false);
final CardView java = root.findViewById(R.id.javacardId);
final CardView html = root.findViewById(R.id.htmlcardId);
final CardView c_prog = root.findViewById(R.id.C_cardId);
final CardView cpp = root.findViewById(R.id.cppcardId);
//set on click listener
java.setOnClickListener(this);
html.setOnClickListener(this);
cpp.setOnClickListener(this);
c_prog.setOnClickListener(this);
return root;
}
#Override
public void onClick(View v) {
Intent i;
switch(v.getId()){
case R.id.javacardId :
i = new Intent(this,html.class);
startActivity(i);
break;
case R.id.htmlcardId :
i = new Intent(this,html_prog.class);
startActivity(i);
break;
case R.id.cppcardId :
i = new Intent(this,cpp_prog.class);
startActivity(i);
break;
case R.id.C_cardId :
i = new Intent(this,c_prog.class);
startActivity(i);
break;
default: break;
}
}
}
---
I expect the card view in that fragment to open up new activity
Try changing the "this" keyword to getContext()
"i = new Intent(this,html.class);"
should be
i = new Intent(getContext,html.class);
or initialize and set the clicklistener in onViewCreated() lifecycle method of Fragment.
You have to use getActivity() instead of 'this' in a fragment for context like below.
#Override
public void onClick(View v) {
Intent i;
switch(v.getId()){
case R.id.javacardId :
i = new Intent(getActivity(),html.class);
startActivity(i);
break;
default: break;
}
The first parameter required by Intent is Context
As mentioned in the Android documentation (Here):
packageContext Context: A Context of the application package implementing this class.
Hence, you need to pass getContext() or getActivity() (since Activity extends Context) as follows:
i = new Intent(getActivity(), html.class);
startActivity(i);
I tried building and launching an app using your code (after making the change above) and it worked fine.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I want to make a communication between my fragment and main activity so I need to get switch.isCheked but get:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.app.Activity.findViewById(int)' on a null object reference
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotesFragment()).commit();
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);
final NotesFragment notesFragment = new NotesFragment();
final RemindersFragment remindersFragment = new RemindersFragment();
final SettingsFragment settingsFragment = new SettingsFragment();
final Switch aSwitch = settingsFragment.getView().findViewById(R.id.switch_pop_up);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
Fragment selectedFragment = null;
switch (menuItem.getItemId()) {
case R.id.action_notes:
if(aSwitch.isChecked())
Toast.makeText(MainActivity.this, "Your Notes", Toast.LENGTH_SHORT).show();
selectedFragment = notesFragment;
break;
case R.id.action_reminders:
if(aSwitch.isChecked())
Toast.makeText(MainActivity.this, "Your Reminders", Toast.LENGTH_SHORT).show();
selectedFragment = remindersFragment;
break;
case R.id.action_settings:
if(aSwitch.isChecked())
Toast.makeText(MainActivity.this, "Settings", Toast.LENGTH_SHORT).show();
selectedFragment = settingsFragment;
break;
}
assert selectedFragment != null;
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
selectedFragment).commit();
return true;
}
});
}
}
SettingsFragment.java
public class SettingsFragment extends Fragment {
Switch switch_pop_up;
boolean stateSwitchPopUp;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_settings, null);
switch_pop_up = v.findViewById(R.id.switch_pop_up);
return inflater.inflate(R.layout.fragment_settings,container,false);
}
}
I think it is because of :
final Switch aSwitch = settingsFragment.getView().findViewById(R.id.switch_pop_up);
How can I fix this?
The problems are:
you are not attaching your SettingsFragment to activity to make it visible on screen (like you do with your NotesFragment)
you're trying to access it's child views from your MainActivity's onCreate method.
Fragments get initialized after activity is being created and ready to host them. Therefore, settingsFragment.getView() is returning null. It's onCreateView lifecycle method has not being called yet.
You need to reconsider your approach and try to find other solution. I suggest you to read this threads in SO to get more ideas on how to solve your problem.
How to access Fragment's child views inside fragment's parent Activity?
Access Fragment View from Activity's onCreate
Android: how to notify Activity when Fragments views are ready?
On your fragment, in the onCreateView method, change this line:
View v = inflater.inflate(R.layout.fragment_settings, null);
into:
View v = inflater.inflate(R.layout.fragment_settings, container, false);
Edit 1:
This happens because you're doing v.findViewById(), but you're not returning v on onCreateView().
Change your return line in the fragment to return v;
Edit 2:
Add a getter on the fragment to the switch_pop_up:
public Switch getSwitchPopUp() {
return switch_pop_up;
}
On your activity, replace this line:
final Switch aSwitch = settingsFragment.getView().findViewById(R.id.switch_pop_up);
with:
final Switch aSwitch = settingsFragment.getSwitchPopUp();
And you'll have to inflate your SettingsFragment before this line.
Note: Whichever result you need, this is not a good aproach anyway, so you might want to look into other ways to do it.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_create: //run NoteActivity in new note mode
startActivity(new Intent(this, NoteActivity.class));
break;
case R.id.action_theme:
setTheme(R.style.Theme2);
setContentView(R.layout.activity_main);
Intent i = getIntent();
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
// TODO: show settings activity
break;
}
return super.onOptionsItemSelected(item);
}
I have a menu item at the top of my activity. I would like to use it to change the theme when pressed. I want to do this after the user has started the program and it will be eventually used to cycle through a bunch of different themes! Right now I just want to get it to work with one. How can I do this?
My Answer
Main Activity
SharedPreferences pref;
SharedPreferences.Editor editor;
int check;
int newcheck;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pref = getApplicationContext().getSharedPreferences("test", Context.MODE_PRIVATE);
check = pref.getInt("x", 0);
if(check == 0){
setTheme(R.style.AppTheme);
}else{
setTheme(R.style.Theme2);
}
setContentView(R.layout.activity_main);
noteActivity = new NoteActivity();
mListNotes = (ListView) findViewById(R.id.main_listview);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_create: //run NoteActivity in new note mode
startActivity(new Intent(this, NoteActivity.class));
break;
case R.id.action_theme:
pref = getApplicationContext().getSharedPreferences("test", Context.MODE_PRIVATE);
editor = pref.edit();
newcheck = pref.getInt("x",0);
if(newcheck == 0) {
newcheck = 1;
}else if(newcheck == 1){
newcheck = 0;
}
editor.clear();//clears the editor to avoid errors
editor.putInt("x",newcheck);//add in new int
editor.commit();//commit
//restart the activity
Intent i = getIntent();
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
finish();//close activity - avoid crash
startActivity(i);//start activity
//TODO show settings activity
break;
}
return super.onOptionsItemSelected(item);
}
So as far as I've understood your problem, you might consider thinking of taking a parent Activity and set a Fragment in there so that you can change the theme of your Fragment where the control of changing the theme is from your parent Activity. So here's how you can achieve this behaviour.
Get a fragment container in your Activity and launch your Fragment in that container in the onCreate function of your Activity.
As you're having a menu option button to decide which theme to be deployed in the Fragment you might consider replacing your Fragment again by doing another fragment transaction when your menu option is clicked.
You might consider saving the selected theme in SharedPreferences so that each time your Fragment launches, you can set the theme properly by setting it in your onCreateView function of your Fragment after reading the selected theme from your SharedPreferences.
Now if you're thinking of how you can set a theme in your Fragment then this post might help you in this regard. I'm copying the code from there for your convenience.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// create ContextThemeWrapper from the original Activity Context with the custom theme
final Context contextThemeWrapper = new ContextThemeWrapper(getActivity(), R.style.yourCustomTheme);
// clone the inflater using the ContextThemeWrapper
LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);
// inflate the layout using the cloned inflater, not default inflater
return localInflater.inflate(R.layout.yourLayout, container, false);
}
I hope you get the idea already. Please let me know if there's anything else you need clarification about.
I tried to phrase the title as I can, but Basically inside the HomeActivity I have a custom menu with a bunch for fragments.! One of the them is HomeFragment which contains a Tablelayout of 2 tabs with a viewpager..!
Everything is working correctly.! but inside the menu fragment, when the user clicks the back button on the toolbar is to return to the HomeFragment.
A fragment replacement method will do the trick which I already used it to replace between the fragments when choosing from the menu !?
But in this case, the HomeFragment opens yet the Tablayout isn't responsive! it feels like the the fragment isn't created correctly!?
I tried using a new intent of the same activity which opens HomeFragment by default, and it opens it but with the same problem..!
The Problem
The Code
HomeFragment
// code..
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
InitViews(rootView);
TabLayoutAdapter adapter = new TabLayoutAdapter(getFragmentManager());
pager.setAdapter(adapter);
tabLayout.setupWithViewPager(pager);
return rootView;
}
// code..
Menu Fragment
// code..
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.to_home:
replaceFragment(new HomeFragment());
// tried this and it's the same problem
// startActivity(new Intent(getActivity(), HomeActivity.class).setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void replaceFragment(Fragment fragment) {
android.support.v4.app.FragmentTransaction t = getFragmentManager().beginTransaction();
t.replace(R.id.Container, fragment);
t.commit();
}
// code..
Looking at the code I think you have to use getChildFragmentManager() instead of getFragmentManager() and use it for fragment Transaction.
The definition of getChildFragmentManager() is:
Return a private FragmentManager for placing and managing Fragments inside of this Fragment.
And the definition of getFragmentManager() is:
Return the FragmentManager for interacting with fragments associated with this fragment's activity.
Replace this line of code having getFragmentManager() by getChildFragmentManager()
TabLayoutAdapter adapter = new TabLayoutAdapter(getChildFragmentManager());
Also in the menu Fragment
android.support.v4.app.FragmentTransaction t = getChildFragmentManager().beginTransaction();
I am trying to send data from one fragment to another, I am using bundle for that. But, whenever, I try to get any information from that bundle in the second fragment, I get an error message saying that I am trying to get a null object. I have set the arguments of the second fragment before I create it, and I have also add information to the bundle before sending it. I could not find out what is the problem. Here is the interface code in the main fragment which should open the details fragment,
public interface ListClickHandler {
public void onlistElementClicked ( Bundle args); //we'll have to override it in the parent activity.
}//end interface.
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (ListClickHandler) activity;
}//end try
catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement ListClickHandler interface");
}//end catch
}
Also, I create the bundle in two places, once in the main fragment, which contains a list, if any item is clicked the bundle is created, info is added to the bundle, and that bundle is passed to the method inside the interface as the following,
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_todo_list, container, false);
mSimpleCursorAdapter=new SimpleCursorAdapter(getActivity(),R.layout.notes_row,null, from, to,0);
getLoaderManager().initLoader(LOADER_ID, null, this); //once this is done onCreateLoader will be called.
ListView listView = (ListView) rootView.findViewById(R.id.notes_list); //findViewById must be called using the rootView because we are inside a fragment.
listView.setAdapter(mSimpleCursorAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
Cursor cursor = mSimpleCursorAdapter.getCursor();
if (cursor != null && cursor.moveToPosition(position)) {
String category= cursor.getString(1);
String summary= cursor.getString(2);
String description=cursor.getString(3);
long id= cursor.getLong(cursor.getColumnIndex(NotesContract.NotesTable._ID));
int locationId= cursor.getInt(cursor.getColumnIndex(NotesContract.NotesTable.COLUMN_LOCATION));
String [] retrievedData= {category, summary, description};
if (getActivity().findViewById (R.id.fragment_container)!=null){
//two pane layout:
Bundle args = new Bundle();
args.putStringArray("data",retrievedData);
/*args.putInt("update", 1);*/
args.putLong("id", id);
args.putInt("locationId", locationId);
mCallback.onlistElementClicked(args );/*this is available in the parent activity*/
}
else {
// one pane layout:
Intent intent = new Intent(getActivity(), NotesDetails.class);
intent.putExtra(Intent.EXTRA_TEXT, retrievedData);
/*intent.putExtra("update", 1); */ //to indicate that the query should be update not insert.
intent.putExtra("id", id);
intent.putExtra("locationId", locationId); //whether it is 0 or 1
startActivity(intent);
}
}//end outer cursor if.
}
});
return rootView;
}
The second place where I create and call the bundle is in the main activity (which contains the main fragment) when some items of the options menu are selected as the following,
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {//open the settings activity to enable the user to change the settings.
//open settings activity via intent here.
startActivity(new Intent (this, Settings.class));
return true;
}
if (id==R.id.text_note){ //open the details activity where the user can enter their notes and save it.
if (twoPane) {
args.putBoolean("location", false);
mCallBack.onlistElementClicked(args);
}
else {
Intent intent = new Intent(this, NotesDetails.class);
startActivity(intent);
return true; //this line is necessary
}
}//end if
if (id==R.id.location_note)
{
if (twoPane) {
args.putBoolean("location", true);
mCallBack.onlistElementClicked(args);
}
else {
//prepare intent here:
Intent intent = new Intent(this, NotesDetails.class);
intent.putExtra("location", true);
startActivity(intent);
}
}
return super.onOptionsItemSelected(item);
}
This is how I override onlistElementClicked in the main activity,
#Override
public void onlistElementClicked(Bundle args) {
DetailsFragment detailsFragment = new DetailsFragment();
detailsFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, detailsFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}//end interface method.
And this is how I get the information inside the arguments of the details fragment (The fragment that should be opened from the main fragment).
Bundle args=this.getArguments();
After that I use args to get any information in the bundle, but I am getting the error which I mentioned previously.
Can any one please help me? I've checked several solutions on the web and nothing worked for me.
Thank you.
You should assign the value of Bundle like this:
public void onCreate(Bundle savedInstance){
super.onCreate(savedInstance);
youtBandGlobalMember = getArguments();
}
Bundle args=this.getArguments();
actually, I didn't call it in any method, it is called in the body of fragment class, and its value is assigned to a global variable. Is that wrong?
It's too early. Member variables are initialized when the object is constructed and that is before you can call setArguments() on the fragment object.
Postpone the getArguments() call to one of the on...() lifecycle callbacks in the fragment.