I've been searching for a while now, but I can't seem to find an answer to the following question:
Why does onCreateView never get triggered? This code is the code generated by Android Studio when creating a new MainActivity plus some of the code I wrote.
I want to use setTextConfig(...,...,...) to set the text in the text fields. But I can't seem to get them using findviewbyid(R.id....); because v is always null, even getView(); returns null.
public static class PlaceholderFragment extends Fragment {
private View v;
private EditText etCustomerName, etDeviceID;
private Spinner select;
public PlaceholderFragment() {
super();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
v = inflater.inflate(R.layout.fragment_main, container, false);
return v;
}
public void setTextConfig(String customerName, String selectedOption, int deviceID){
View vv = getView();
//init form controls
etCustomerName = (EditText)vv.findViewById(R.id.etCustomerName);
etDeviceID = (EditText)v.findViewById(R.id.etDeviceId);
select = (Spinner)v.findViewById(R.id.select);
etCustomerName.setText(customerName);
ArrayAdapter adapter = (ArrayAdapter)select.getAdapter();
int index = adapter.getPosition(selectedOption);
select.setSelection(index);
etDeviceID = (EditText)getView().findViewById(R.id.etDeviceId);
etDeviceID.setText(Integer.toString(deviceID), TextView.BufferType.EDITABLE);
}
}
If you need more detailed info, just ask :)
Related
I am trying to get an ArrayList from an activity and then display it inside a fragment in a custom adapter. The problem it's that I cannot setAdapter to do so. The error it says the context it's wrong, when I created the Adapter.
Creare_istoricAdapter class:
public class Creare_istoricAdapter extends ArrayAdapter<Creare_istoric> {
private static final String TAG = "Creareistoric_adapter";
private Context mContext;
int mResource;
public Creare_istoricAdapter(#NonNull Context context, int resource, #NonNull ArrayList<Creare_istoric> objects) {
super(context, resource, objects);
mContext = context;
mResource = resource;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
String id_alerta = getItem(position).getId_alerta();
String tip_problema = getItem(position).getTip_problema();
String data_ora= getItem(position).getData_ora();
String stare_problema = getItem(position).getStare_problema();
String descriere = getItem(position).getDescriere();
Creare_istoric istoric = new Creare_istoric(id_alerta, tip_problema, data_ora, stare_problema, descriere);
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
TextView text_tip_alerta_istoric = convertView.findViewById(R.id.text_tip_alerta_istoric);
TextView text_ora_alerta_istoric = convertView.findViewById(R.id.text_ora_alerta_istoric);
TextView text_stare_alerta_istoric = convertView.findViewById(R.id.text_stare_alerta_istoric);
text_tip_alerta_istoric.setText(tip_problema);
text_ora_alerta_istoric.setText(data_ora);
text_stare_alerta_istoric.setText(stare_problema);
return convertView;
}
}
The fragment class:
public class Fragment_alerte_trimise extends Fragment {
public Fragment_alerte_trimise(){}
ListView list_view_alerte_trimise;
ArrayList<Creare_istoric> alerteTrimise= new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View alerte_trimise = inflater.inflate(R.layout.fragment_alerte_trimise,container, false);
return alerte_trimise;
Bundle bundle_trimise;
if (bundle_trimise != null) {
alerteTrimise = bundle_trimise.getParcelableArrayList("alerte_trimise");
}
list_view_alerte_trimise =getView().findViewById(R.id.list_view_alerte_trimise);
Creare_istoricAdapter adapter = new Creare_istoricAdapter(this, R.layout.istoric_alerte_adapter, alerteTrimise);
list_view_alerte_trimise.setAdapter(adapter);
}
}
The problems it's in new Creare_istoricAdapter(this, R.layout.istoric_alerte_adapter, alerteTrimise) , about the context, and is also greyed out, saying it's redundant.
EDIT:
I have changed the code following the answers below, but now when I open the activity that uses the fragment, it does not show the list at all. It's only an blank screen.
The fragment code:
public class Fragment_alerte_trimise extends Fragment {
public Fragment_alerte_trimise(){}
private ListView list_view_alerte_trimise;
ArrayList<Creare_istoric> alerteTrimise= new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View alerte_trimise = inflater.inflate(R.layout.fragment_alerte_trimise,container, false);
return alerte_trimise;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Bundle bundle_trimise = getArguments();
if (bundle_trimise != null) {
alerteTrimise = bundle_trimise.getParcelableArrayList("alerte_trimise");
}
list_view_alerte_trimise =getView().findViewById(R.id.list_view_alerte_trimise);
list_view_alerte_trimise.setAdapter(new Creare_istoricAdapter(getContext(), R.layout.istoric_alerte_adapter, alerteTrimise));
}
}
The way I created the Parceable:
Bundle bundle_trimise = new Bundle();
bundle_trimise.putParcelableArrayList("alerte_trimise", alerteTrimise);
Fragment_alerte_trimise fg = new Fragment_alerte_trimise();
fg.setArguments(bundle_trimise);
I have the ListView created in the layout that's inflated by the onCreateView, but when I use getView().findViewById it says that it may produce 'NullPointerException', and so does the getContext(), which says it might be null
Please try to use getContext() instead of this.
You have to use activity context instead of fragment context this. Instead of using getContext() or getActivity() you should initialize the context on onAttach to avoid NullPointerException. Check below:
private Context activityContext;
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
activityContext = context;
}
#Override
public void onDetach() {
super.onDetach();
activityContext = null;
}
Beside this, you have to return the view inside onCreateView at the very end. Check below:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
....
// use alerte_trimise instead of getView()
list_view_alerte_trimise = alerte_trimise.findViewById(R.id.list_view_alerte_trimise);
//use activityContext instead of this
Creare_istoricAdapter adapter = new Creare_istoricAdapter(activityContext, R.layout.istoric_alerte_adapter, alerteTrimise);
....
return alerte_trimise;
}
In your code, you try to use Bundle after call return. That's why rest of your code is unreachable.
You are using Creare_istoricAdapter in your Fragment_alerte_trimise so it needs context. therefor we can give activity context or application context(beyond the activity level)
Moreover...
getContext() - Returns the context view only current running activity.
getActivity()- Return the Activity this fragment is currently associated with.
getActivity() can be used in a Fragment for getting the parent Activity of the Fragment.
Add this code changes to your code.
getActivity().getApplicationContext()
Use getContext() instead of this. this refers to current object (Fragment), which is not subclass of Context.
Create adapter in onViewCreated(), because getContext() returns null in onCreateView().
I have a navigation drawer activity where i am attaching different fragments
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, rp_fragment.OnFragmentInteractionListener, sensors_fragment.OnFragmentInteractionListener, stats_fragment.OnFragmentInteractionListener {
I'm trying to modify the text property of a textview contained within a fragment but i keep getting a null pointer exception on the view (java.lang.NullPointerException: Attempt to invoke virtual method 'void com.teicrete.alucard.sempi.sensors_fragment.ctv_tvst(int)' on a null object reference).
Mainactivity:
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (id == R.id.nav_camera) {
ft.replace(R.id.fragment_placeholder, new rp_fragment());
ft.commit();
} else if (id == R.id.nav_gallery) {
ft.replace(R.id.fragment_placeholder, new sensors_fragment());
ft.commit();
gentempdata();
sensors_fragment sf = (sensors_fragment)fm.findFragmentById(R.id.fragment_sensors);
sf.ctv_tvst(1);
Fragment:
public class sensors_fragment extends Fragment {
// 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";
TextView ctv_tv;
TextView otv_tv;
View view;
...
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_sensors, container, false);
TextView ctv_tv = (TextView)view.findViewById(R.id.ctv_tv);
TextView otv_tv = (TextView)view.findViewById(R.id.otv_tv);
//ctv_tv.setText("Test"); Only this works
return view;
}
...
public void ctv_tvst(int mtext) {
ctv_tv.setText(mtext);
}
I've looked at similar posts here but i was not able to resolve my issue. The only place where i am able to modify the textview is within the onCreateView of the fragment (see code above). If i try to do it from the mainactivity or anywhere else i get the null pointer error.
Any insights?
Edit: Please see my response in android_griezmann's post.
For now, i am doing everything that i need to do, inside the fragment classes themselves and then i load them. I would still like to figure out why i can't access its methods or views externally.
Change those lines from onCreateView:
TextView ctv_tv = (TextView)view.findViewById(R.id.ctv_tv);
TextView otv_tv = (TextView)view.findViewById(R.id.otv_tv);
To:
ctv_tv = (TextView)view.findViewById(R.id.ctv_tv);
otv_tv = (TextView)view.findViewById(R.id.otv_tv);
Currently you are assigning reference to new object by TextView ctv_tv but actually you want this reference to be assigned to class field so you don't have to add TextView.
Your problem is Fragment itself not the TextView. You are getting fragment object as null not the textview.
So try to find the fragment like the below.
if (id == R.id.nav_gallery) {
ft.replace(R.id.fragment_placeholder, new sensors_fragment(),"YOUR_TAG_NAME");
ft.commit();
gentempdata();
sensors_fragment sf = (sensors_fragment) fm.findFragmentByTag("YOUR_TAG_NAME");
sf.ctv_tvst(1);
}
Also change this method too!
public void ctv_tvst(int mtext) {
ctv_tv.setText("" + mtext);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TextView ctv_tv = (TextView)getView().findViewById(R.id.ctv_tv);
TextView otv_tv = (TextView)getView().findViewById(R.id.otv_tv);
}
override onactivity created, and then refer your views.. Infact it is the best place to get reference to your views withot getting NullPointer Exception
If you want to pass data while replacing or adding then pass the data in your fragment constructor like below
else if (id == R.id.nav_gallery) {
ft.replace(R.id.fragment_placeholder, new sensors_fragment("your data"));
ft.commit();
Then in your fragmet change the textview value based on the constructor's data
Here is the problem. Just remove the TextView
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_sensors, container, false);
**TextView** ctv_tv = (TextView)view.findViewById(R.id.ctv_tv);
**TextView** otv_tv = (TextView)view.findViewById(R.id.otv_tv);
//ctv_tv.setText("Test"); Only this works
return view;
}
Replace the following code
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_sensors,container, false);
TextView ctv_tv = (TextView)view.findViewById(R.id.ctv_tv);
TextView otv_tv = (TextView)view.findViewById(R.id.otv_tv);
//ctv_tv.setText("Test"); Only this works
return view;
}
with
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_sensors,container, false);
ctv_tv = (TextView)view.findViewById(R.id.ctv_tv);
otv_tv = (TextView)view.findViewById(R.id.otv_tv);
//ctv_tv.setText("Test"); Only this works
return view;
}
Create a variable String ctv_tv_string and assign the value in ctv_tvst() method do not assign to the TextView. it would not throw an error as you are not referring any ui element after this in oncreateview ctv_tv.setText(ctv_tv_string)
This is the error i get:
03-11 08:27:48.513: E/AndroidRuntime(23647): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.plan.yeahimin/com.plan.yeahimin.PlanDetailsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.Serializable android.os.Bundle.getSerializable(java.lang.String)' on a null object reference
I understand its due to a variable having a null value but I can't workout why. It looks like it's 'EXTRA_NEW_PLAN' in the getSerializable() method in the DetailsFragment but other than that I don't know. I'm new to Android so forgive me if it's obvious but any help would be greatly appreciated.
Here is my code for the ListFragment;
public class PlanListFragment extends ListFragment {
public final static String TAG = "com.plan.yeahimin.PlanListFragment";
public final static String EXTRA_NEW_PLAN = "com.plan.yeahimin.plan_id";
private Button mAddPlan;
private ArrayList<Plan> mPlansList;
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.empty_view_or_list_view, parent, false);
ListView view = (ListView) v.findViewById(android.R.id.list);
view.setEmptyView(v.findViewById(android.R.id.empty));
mAddPlan = (Button) v.findViewById(R.id.add_a_plan);
mAddPlan.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
Log.d(TAG, "add plan clicked");
Plan plan = new Plan();
Log.d(TAG, "new plan created");
PlanArrayList.get(getActivity()).addPlans(plan);
Log.d(TAG, "plan added to mPlansList");
Intent i = new Intent(getActivity(), PlanDetailsActivity.class);
i.putExtra(PlanDetailsFragment.EXTRA_NEW_PLAN, plan.getId());
startActivity(i);
return;
}
});
return v;
}
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mPlansList = PlanArrayList.get(getActivity()).getPlans();
//ArrayList<Plan> mPlansList = new ArrayList<Plan>();
PlanArrayAdapter paa = new PlanArrayAdapter(mPlansList);
setListAdapter(paa);
}
public class PlanArrayAdapter extends ArrayAdapter<Plan>{
public PlanArrayAdapter(ArrayList<Plan> planList){
super(getActivity(), 0, planList);
}
public View getView(int position, View convertView, ViewGroup parent){
// Get the plan item for this position
Plan plan = getItem(position);
//If layout doesnt exist, inflate one
if(convertView == null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.plan_list_fragment, parent, false);
}
TextView planTitle = (TextView) convertView.findViewById(R.id.plan_title);
planTitle.setText(plan.getTitle());
TextView planDate = (TextView) convertView.findViewById(R.id.plan_date);
planDate.setText(plan.getDate().toString());
return convertView;
}
}
}
and here is my code for the DetailsFragment which opens from add button;
public class PlanDetailsFragment extends Fragment {
private static final String TAG = "com.plan.yeahimin.PlanDetailsFragment";
public static final String EXTRA_NEW_PLAN = "com.plan.yeahimin.plan_id";
private EditText mTitleField;
private Button mDateButton;
private Button mTimeButton;
private EditText mLocationField;
private EditText mAttendeesField;
private EditText mDescriptionField;
private Plan mPlan;
private ArrayList<Plan> mPlansList;
public static PlanDetailsFragment newInstance(UUID planId){
Bundle args = new Bundle();
args.putSerializable(EXTRA_NEW_PLAN, planId);
PlanDetailsFragment f = new PlanDetailsFragment();
f.setArguments(args);
Log.d(TAG, "newInstance created");
return f;
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
UUID planId = (UUID)getArguments().getSerializable(EXTRA_NEW_PLAN);
mPlan = PlanArrayList.get(getActivity()).getPlan(planId);
}
#Override
public View onCreateView (LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.plan_details_fragment, parent, false);
mTitleField = (EditText)v.findViewById(R.id.plan_title);
mLocationField = (EditText)v.findViewById(R.id.plan_location);
mAttendeesField = (EditText)v.findViewById(R.id.plan_attendees);
mDescriptionField = (EditText)v.findViewById(R.id.plan_description);
mDateButton = (Button)v.findViewById(R.id.plan_date);
mTimeButton = (Button)v.findViewById(R.id.plan_time);
return v;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
inflater.inflate(R.menu.main_to_do, menu);
}
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case R.id.save_button:
Log.d(TAG, "save button pressed");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
I think you cannot send any arguments to your Fragment with .newInstance(), because this method does not accept any parameters according to the documentation. So even if you have overloaded .newInstance(UUID), the system calls .newInstance() (if calls at all, I have some doubts). Also please be aware that you put the parameter to Intent with .putExtra(), but do not recall it from the Intent.
In fact the right way to send arguments to a Fragment is as follows:
In the caller (usually it is an Activity, but maybe with another Fragment, like in your example, it would also work, I cannot say for sure):
PlanDetailsFragment fragment = new PlanDetailsFragment();
Bundle args = new Bundle();
args.putSerializable(PlanDetailsFragment.TAG_NEW_PLAN, plan.getID());
fragment.setArguments(args);
getFragmentManager().beginTransaction().add(fragment, TAG_DETAILS_FRAGMENT).commit();
In the fragment:
Bundle args = getArguments();
UUID planID = (UUID) args.getSerializable(TAG_NEW_PLAN);
It is not a ready-to-use code, you should adapt it to your classes and variables names, to where your tags are places, etc. The calls of Activity methods may also require some change if you prefer to work from another fragment. It is just an overall description.
My answer applies to the situation when both fragments are inside one activity. Your using of Intents make me have doubts in this, but I do not fully understand it.
You sent the arguments to an Activity(PlanDetailsActivity).
You should send the arguments to a Fragment through newInstance() method.
In your PlainDetailsActivity, you should create the fragment instance like:
UUID uuid = getIntent().getSerializableExtra(PlanDetailsFragment.EXTRA_NEW_PLAN);
PlanDetailsFragment f = PlanDetailsFragment.newInstance(uuid);
I am trying to create a circle inside a fragment and I need to change its color in runtime in future.
but the method setBackgroundDrawable gives me nullPointerException.
I am not able to figure it out as I am web developer and I am new to android development. Please help me.
And the code is below
public class tester extends Fragment {
private View circle_holder;
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.today, container, false);
circle_holder = (View)getActivity().findViewById(R.id.cicle);
ShapeDrawable mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(Color.RED);
if (Build.VERSION.SDK_INT >= 16){
circle_holder.setBackground(mDrawable);
}
else{
circle_holder.setBackgroundDrawable(mDrawable);
}
return rootView;
}
}
Change this line.
circle_holder = (View)getActivity().findViewById(R.id.cicle);
into
circle_holder = (View)rootView .findViewById(R.id.cicle);
I am trying to use the method
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a DummySectionFragment (defined as a static inner class
// below) with the page number as its lone argument.
Fragment fragment = new MappingPage();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
return fragment;
}
I have written a class called MappingPage(), if I try to use the above method, the fragment I create is of type MappingPage because has been extended and hence throw an error as the function returns a fragment (not a MappingPage Object)
EDIT:I am getting an error when I do
Fragment fragment = new MappingPage();
Eclipse tell me that I need to change fragment to type MappingPage, which means i have to change the return type of the function
two Questions
1) How are you supposed to put your custom fragments into this?
2) Why does the dummySectionFrament return a Fragment Object and not a DummySectionFragment object?
thanks in advance
public static class DummySectionFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
public static final String ARG_SECTION_NUMBER = "section_number";
public DummySectionFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main_dummy,
container, false);
TextView dummyTextView = (TextView) rootView
.findViewById(R.id.section_label);
dummyTextView.setText(Integer.toString(getArguments().getInt(
ARG_SECTION_NUMBER)));
return rootView;
}
}
here is my class
public class MappingPage extends Fragment
{
private MapView map;
private MapController myMapController;
public static final String ARG_SECTION_NUMBER = "1";
public MappingPage() {
}
public View onCreateView (LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Context context = new ContextThemeWrapper(getActivity(), R.style.fragment_theme);
//LayoutInflater Inflater = inflater.cloneInContext(context);
View view=inflater.inflate(R.layout.fragment_main_dummy, container, false);
return view;
}
#Override
public void onResume() {
map = (MapView)getActivity().findViewById(R.id.openmapview);
map.setBuiltInZoomControls(true);
myMapController = map.getController();
myMapController.setZoom(15);
super.onResume();
}
}
Regarding your first question, this should work. MappingPage is an indirect instance of the Fragment class, and you can therefore return it.
About question two, the method that you call always returns a specific type, like Fragment in the case of getItem(). However, this can be a subclass of that as well, and if you are sure it is, you can safely cast it to that subclass.