am trying to use a spinner within a fragment to categorize the output of my recycler view
when I call the recycler view function from the onCreateView it works perfectly. however, when I call it from the spinner function, it requires 2 clicks to display.
here is the spinner XML code:
<Spinner
android:id="#+id/med_spinner"
android:layout_width="150dp"
android:layout_height="30dp"
android:layout_below="#+id/tv_med2"
android:layout_marginLeft="15dp"
android:layout_marginTop="20dp"
android:layout_toRightOf="#id/tv_spinner"
android:dropDownWidth="match_parent"
android:focusable="true"
android:gravity="center"
android:entries="#array/medicine"
/>
and here is the fragment:
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_medicine, container, false);
RecyclerView rv_med = view.findViewById(R.id.rv_medicine);
db = new UserDB(getActivity());
med_name = new ArrayList<>();
med_type = new ArrayList<>();
med_type2 = new ArrayList<>();
//spinner declartion
spinner = view.findViewById(R.id.med_spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.medicine, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(this);
//recycler view adapter and layout manger
recyclerViewAdapter = new RecyclerViewAdapterMedicine(getContext(), med_name, med_type, med_type2);
rv_med.setAdapter(recyclerViewAdapter);
rv_med.setLayoutManager(new LinearLayoutManager(getContext()));
return view;
}
and here is the spinner functions
#Override
public void onItemSelected(AdapterView<?> parent, View view, int i, long l) {
med_name.clear();
med_type.clear();
med_type2.clear();
cata = spinner.getSelectedItem().toString();
display(cata);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
cata = "All";
display(cata);
}
here's the display function:
void display(String type) {
db.open();
Cursor cursor = db.listMedicine();
if (cursor.getCount() == 0) {
Toast.makeText(getActivity(), "an error occurred", Toast.LENGTH_LONG).show();
} else {
if (type.equals("All")){
while (cursor.moveToNext()) {
med_name.add(cursor.getString(1));
med_type.add(cursor.getString(2));
med_type2.add(cursor.getString(3));
}
}else{
while (cursor.moveToNext()) {
if(cursor.getString(2).equals(type) || cursor.getString(3).equals(type)) {
med_name.add(cursor.getString(1));
med_type.add(cursor.getString(2));
med_type2.add(cursor.getString(3));
}
}
}
db.close();
}
}
I've tried to put the spinner functions within a spinner.onItemSelectedListener inside and outside the fragment, I tried to enable and disable focus and focusableTochMode, I also tried to call the recycler view before the spinner in the fragment.
You need to notify your RecyclerViewAdapter that data has changed. Add
recyclerViewAdapter.notifyDataSetChanged()
at the end of your display.
Related
I've created a customised list view for my Android app in order to add a Delete button for every cell to make the user able to delete rows from the list. The customised list view is working well but when I added a click listener for the button, the list view show empty cells instead of populating the data coming from the array.
Here is the getView code:
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.row, parent, false);
Button deleteButt = (Button) row.findViewById(R.id.deleteButton);
deleteButt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), "delete me", Toast.LENGTH_SHORT).show();
}
});
return row;
}
I think the I should return something else not the row, but I have no idea what to return. When I think about it when I return the row it should show the rows filled with data. Note when I delete this piece of code, the list view is working well with showing the data.
This is the whole code of the adapter class
// Our adapter class
class MyAdapter extends ArrayAdapter<String> {
Context context;
String rNames[];
MyAdapter(Context c, String name[]) {
super(c, R.layout.row, R.id.customerName, name);
this.context = c;
this.rNames = name;
}
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.row, parent, false);
Button deleteButt = (Button) row.findViewById(R.id.deleteButton);
deleteButt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), "delete me", Toast.LENGTH_SHORT).show();
}
});
return row;
}
}
And this is the whole code of the home fragment page
public class HomeFragment extends Fragment {
// creating an empty array. This is an array of objects (array of arrays).
final ArrayList<String[]> mainObjectsArray = new ArrayList<String[]>();
//final String[][] myFamily = new String[][];
// creating another array of the titles. If our main array is an array of strings we will not need this.
// Why?. ArrayAdapter doesn't accept an array of arrays it only accepts an array of Stings, so we had to create a special array for the titles and bring them from our main array.
final ArrayList<String> theNames = new ArrayList<String>();
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_home, null);
// creaing a list view and connect it to the list view we created in the XML file
// Note: we need to add (final) to be able to access them from inside the loop
final ListView myListView = (ListView) rootView.findViewById(R.id.myListView);
// Retrieving the data and filling the array with it
ParseQuery<ParseObject> query = ParseQuery.getQuery("Orders");
query.orderByDescending("updatedAt");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
//Log.i("findInBackground", "Retrieved: " + objects.size() + "objects");
if (objects.size() > 0) {
for (ParseObject object: objects) {
// Converting every object to an array of two itmes, title and body.
String[] artical = {object.getString("TheSavedOrder"), object.getString("mobileNumber"), object.getString("Name")};
// Adding the array to our main array so we will have an array of arrays
mainObjectsArray.add(artical);
//Log.i("This my family array: ", myFamily.toString());
}
// We will add only the names to the array (theNames). theTitles will be an array of strings so we can populate it in the list view.
for (int i = 0; i < mainObjectsArray.size(); i++){
theNames.add(mainObjectsArray.get(i)[2]);
//Log.i("Here are teh title: ", myFamily.get(i)[0]);
Log.i("Here is thti: ", theNames.get(i));
}
// Converting theNames from ArrayList to an array
String[] namesArray = new String[theNames.size()];
namesArray = theNames.toArray(namesArray);
// Applaying our adapter
MyAdapter adapter = new MyAdapter(getActivity(), namesArray);
myListView.setAdapter(adapter);
}
}
}
});
// When clicking on an item in the list view
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Log.i("The body is: ", mainObjectsArray.get(position));
Intent intent = new Intent(getContext(), TheBody.class);
intent.putExtra("mobile", mainObjectsArray.get(position)[1]); // mainObjectsArray.get(position)[1] means we will pass the second item in every array which is the (mobileNumber).
intent.putExtra("order", mainObjectsArray.get(position)[0]);
startActivity(intent);
}
});
return rootView;
}
// Our adapter class
class MyAdapter extends ArrayAdapter<String> {
Context context;
String rNames[];
MyAdapter(Context c, String name[]) {
super(c, R.layout.row, R.id.customerName, name);
this.context = c;
this.rNames = name;
}
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.row, parent, false);
Button deleteButt = (Button) row.findViewById(R.id.deleteButton);
deleteButt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), "delete me", Toast.LENGTH_SHORT).show();
}
});
return row;
}
}
}
This is the XML code of the fragment
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/myListView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
And finally this is the XML code of the customised cell
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:descendantFocusability="blocksDescendants">
<TextView
android:id="#+id/customerName"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="custoemr name"
android:textColor="#000"
android:layout_margin="5dp"
android:textSize="20sp"/>
<Button
android:id="#+id/deleteButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Delete"
/>
</LinearLayout>
Please help I've been struggling with this for some days!
Many thanks.
public View getView(final int position, View convertView, ViewGroup parent) {
View row = super.getView(position, convertView, parent);
Button deleteButt = (Button) row.findViewById(R.id.deleteButton);
deleteButt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), "delete me", Toast.LENGTH_SHORT).show();
} });
return row;
}
Pls also note that your list, rNames, is an array[] that is fixed size and cannot remove an individual item. You should use ArrayList if you want to implement the delete function.
Updated:
public class HomeFragment extends Fragment {
// creating an empty array. This is an array of objects (array of arrays).
ArrayList<MainObjects> mainObjectsList = new ArrayList<>();
ListView myListView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, null);
// creaing a list view and connect it to the list view we created in the XML file
// Note: we need to add (final) to be able to access them from inside the loop
myListView = (ListView) rootView.findViewById(R.id.myListView);
// Retrieving the data and filling the array with it
ParseQuery<ParseObject> query = ParseQuery.getQuery("Orders");
query.orderByDescending("updatedAt");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
//Log.i("findInBackground", "Retrieved: " + objects.size() + "objects");
if (objects.size() > 0) {
for (ParseObject object : objects) {
// Converting every object to an array of two items, title and body.
//String[] artical = {object.getString("TheSavedOrder"), object.getString("mobileNumber"), object.getString("Name")};
MainObjects article = new MainObjects(object.getString("TheSavedOrder"), object.getString("mobileNumber"), object.getString("Name");
// Adding the array to our main array so we will have an array of arrays
mainObjectsList.add(article);
//Log.i("This my family array: ", myFamily.toString());
}
// Applying our adapter
MyAdapter adapter = new MyAdapter(getActivity(), mainObjectsList);
myListView.setAdapter(adapter);
}
}
}
});
// When clicking on an item in the list view
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Log.i("The body is: ", mainObjectsList.get(position));
Intent intent = new Intent(getContext(), TheBody.class);
intent.putExtra("mobile", mainObjectsList.get(position).getMobileNumber());
intent.putExtra("order", mainObjectsList.get(position).getSavedOrder());
startActivity(intent);
}
});
return rootView;
}
class MainObjects {
String savedOrder = "", mobileNumber = "", name = "";
public MainObjects(String savedOrder, String mobileNumber, String name) {
this.savedOrder = savedOrder;
this.mobileNumber = mobileNumber;
this.name = name;
}
public String getSavedOrder() {
return savedOrder;
}
public String getMobileNumber() {
return mobileNumber;
}
public String getName() {
return name;
}
}
class MyAdapter extends ArrayAdapter<MainObjects> {
Context context;
LayoutInflater inflater;
ArrayList<MainObjects> rNames;
MyAdapter(Context c, ArrayList<MainObjects> name) {
super(c, R.layout.row, R.id.customerName, name);
this.context = c;
this.rNames = name;
inflater = getLayoutInflater();
}
public View getView(int position, View convertView, ViewGroup parent) {
View row = inflater.inflate(R.layout.row, parent, false);
TextView nameTv = (TextView) row.findViewById(R.id.customerName);
nameTv.setText(getItem(position).getName());
Button deleteButt = (Button) row.findViewById(R.id.deleteButton);
deleteButt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int pos = (int)view.getTag();
String msg = "Delete: " + pos + ". " + getItem(pos).getName() + " !!";
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
rNames.remove(pos);
notifyDataSetChanged();
//
// Codes to update permanent storage, e.g. files/server/db.
//
} });
deleteButt.setTag(position);
return row;
}
}
}
The button view shows confirming that the fragment shows, however the recycler view doesn't.
The logged array size of "jobs" is 1, confirming that getItemCount() isn't the problem and that the recycler adapter constructor is called. I'm reusing my JobRecyclerAdapter class but nothing's static, so there shouldn't be any interference between the two instances. The layout is a a copy of a working one I have, minus different ids and layout name, so that shouldn't be a problem either. There are no errors.
Layout
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<include layout="#layout/top_bar"
android:id="#+id/topBarAJ"
android:layout_height="wrap_content"
android:layout_width="match_parent"
app:layout_constraintTop_toTopOf="parent"/>
<include layout="#layout/bottom_bar"
android:id="#+id/bottomBarAJ"
android:layout_height="wrap_content"
android:layout_width="match_parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/activeJobRecyclerView"
app:layout_constraintTop_toBottomOf="#id/topBarAJ"
app:layout_constraintBottom_toTopOf="#id/bottomBarAJ"/>
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toTopOf="#+id/activeJobRecyclerView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.505"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/topBarAJ" />
</androidx.constraintlayout.widget.ConstraintLayout>
RecyclerAdapter
List<Job> jobs;
List<Drawable> images;
RecyclerViewClickListener clickListener;
public JobRecyclerAdapter(List<Job> downloadedJobs, List<Drawable> images, RecyclerViewClickListener clickListener) {
this.jobs = downloadedJobs;
this.images = images;
Integer arraySize = images.size();
Log.d("downloadActiveJob", "JobRecyclerAdapter: images array size: " + arraySize.toString());
arraySize = jobs.size();
Log.d("downloadActiveJob", "JobRecyclerAdapter: jobs array size: " + arraySize.toString());
this.clickListener = clickListener;
}
class JobCardViewHolder extends RecyclerView.ViewHolder {
public ImageView itemImage;
public TextView itemName;
public TextView itemWeight;
public TextView itemSize;
public TextView transmitterName;
public JobCardViewHolder(View v) {
super(v);//call default constructor
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("RecyclerView", "onClick:" + getAdapterPosition());
clickListener.recyclerViewListClicked(v, getAdapterPosition());
}
});
itemImage = (ImageView) v.findViewById(R.id.itemImage);
itemName = (TextView) v.findViewById(R.id.itemName);
itemWeight = v.findViewById(R.id.itemWeight);
itemSize = v.findViewById(R.id.itemSize);
transmitterName = v.findViewById(R.id.transmitterName);
}
}
public void removeItem(int jobIndex) {
jobs.remove(jobIndex);
notifyDataSetChanged();
}
#Override
public JobCardViewHolder onCreateViewHolder(ViewGroup vg, int n) {
View v = LayoutInflater.from(vg.getContext()).inflate(R.layout.job_card_layout, vg, false);
JobCardViewHolder vH = new JobCardViewHolder(v);
return vH;
}
#Override
public void onBindViewHolder(JobCardViewHolder vH, int position) {
vH.itemName.setText(jobs.get(position).itemName);
vH.itemImage.setImageDrawable(images.get(position));
vH.itemWeight.setText(jobs.get(position).itemWeight);
vH.itemSize.setText(jobs.get(position).itemSize);
vH.transmitterName.setText(jobs.get(position).transmitterName);
}
#Override
public int getItemCount() {
return jobs.size();
}
}
Fragment (I only showed the relevant parts of the fragment.)
RecyclerView jobRecyclerView;
JobRecyclerAdapter jobRecyclerAdapter;
LinearLayoutManager llm;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.sub_fragment_active_jobs_1, container, false);
this.jobRecyclerView = view.findViewById(R.id.activeJobRecyclerView);
return view;
}
public void configureJobsRecyclerAdapter(Job activeJob, List<Drawable> imageDrawables) {
Log.d("downloadActiveJob", "configureJobRecyclerAdapter called");
List<Job> downloadedJobs = new ArrayList<>();
downloadedJobs.add(activeJob);
Integer arraySize = imageDrawables.size();
Log.d("downloadActiveJob", "configureJobRecyclerAdapter: " + arraySize.toString());
jobRecyclerAdapter = new JobRecyclerAdapter(downloadedJobs, imageDrawables, this);
llm = new LinearLayoutManager(context);
jobRecyclerView.setLayoutManager(llm);
jobRecyclerView.setAdapter(jobRecyclerAdapter);
}
Update: If I move the recycler view/adapter setup code to onResume, the recycler view is visible. When I update the recycler view with a new adapter, the recycler view becomes invisible.
If I can't solve it using this new discovery I'll post the whole fragment.
Hey, you create the function configureJobsRecyclerAdapter() but didn't call it inside fragment onCreateView(). Like...
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.sub_fragment_active_jobs_1, container, false);
this.jobRecyclerView = view.findViewById(R.id.activeJobRecyclerView);
configureJobsRecyclerAdapter()//Add this line.
return view;
}
if you are fetching data which are required for configureJobsRecyclerAdapter() from an api maybe you are setting empty list at the time when you are calling configureJobsRecyclerAdapter(). and that's why when you call it in onResume, the list becomes visible(because then data is fetched).
and don't forget to call adapter.notifyDataSetChanged() after each change in your list.
Ok, I have an Listview adapter that contains an ImageView, TextView and another ImageView in that order. So I want to be able to delete the item in list when user presses on second ImageView. When the user press on the item in list it will start TextToSpeech and it will say what is inside TextView. But if the user wants to remove the entry he/she will press on second ImageView which is a delete icon, at that point the item will be remove from the list. Starting the click listener for the imageview is not a problem, the problem is how do I get the number (int) of the corresponding item in listview adapter so I can remove it from array. Here's xml list_item.xml for single entry in list
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="3dp"
android:layout_marginBottom="3dp">
<ImageView
android:id="#+id/item_icon_imageview"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.15"
android:src="#drawable/ic_record_voice_24dp2"/>
<TextView
android:id="#+id/phrase_textview"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.80"
android:textSize="20sp"
android:layout_marginTop="5dp"
android:text="My phone number is 305 666 8454"/>
<ImageView
android:layout_gravity="center"
android:id="#+id/delte_item_imageview"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.10"
android:src="#drawable/ic_delete_black_24dp"/>
</LinearLayout>
</RelativeLayout>
The fragment for inflating the listview
public class CustomFragment extends Fragment {
private ArrayAdapter<String> adapter;
private ListView listView;
private FloatingActionButton addPhraseButton;
private TextView phraseTitleTextView;
private TextToSpeech textToSpeech;
private ArrayList<String> phrases;
private static final String PHRASE_LABEL = " Phrases";
private static final String CATEGORY_KEY = "categories";
private ImageView deleteItemImageView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_custom, container, false);
final String categories;
//if we selecte a category sent from home fragment else we got here through menu
Bundle arguments = getArguments();
if (arguments != null && arguments.containsKey(CATEGORY_KEY)) {
categories = arguments.getString(CATEGORY_KEY).toLowerCase();
}
else {
Resources res = view.getResources();
categories = res.getStringArray(R.array.categories)[0].toLowerCase();
}
final Phrases allPhrases = Phrases.getPhrases();
allPhrases.fetchAllPhrases(view.getContext());
phrases = allPhrases.getAllPhrases().get(categories);
phraseTitleTextView = view.findViewById(R.id.label_phrases_txtview);
deleteItemImageView = view.findViewById(R.id.delte_item_imageview);
phraseTitleTextView.setText(categories.substring(0,1).toUpperCase() +
categories.substring(1)+ PHRASE_LABEL);
addPhraseButton = view.findViewById(R.id.add_phrases_btn);
// setting local for text to speech
textToSpeech = new TextToSpeech(getActivity().getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
textToSpeech.setLanguage(Locale.US);
}
});
//setting adapter and listview
adapter = new ArrayAdapter<String>(getContext(), R.layout.entry_item, R.id.phrase_textview, phrases);
listView = (ListView) view.findViewById(R.id.phrases_list);
listView.setAdapter(adapter);
listView.setItemsCanFocus(true);
//activating text to speech when user selects item in listview
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> paren, View view, int position, long id) {
String text = phrases.get(position);
Toast.makeText(getContext(), text, Toast.LENGTH_LONG).show();
textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH,null, null);
}
});
deleteItemImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
//button to display alert dialog box to add new phrase
addPhraseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addPhraseDialogBox();
}
});
return view;
}
}
You can achieve this through Custom Adapter. Check below:
public class CustomArrayAdapter extends ArrayAdapter<String> {
LayoutInflater inflater;
ArrayList<String> phrases;
public CustomArrayAdapter(Context context, int textViewResourceId, ArrayList<String> items) {
super(context, textViewResourceId, items);
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
phrases = items;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.entry_item, parent, false);
}
....
ImageView deleteItemImageview = (ImageView) convertView.findViewById(R.id. delte_item_imageview);
deleteItemImageview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
phrases.remove(position);
notifyDataSetChanged();
}
});
return convertView;
}
}
I have multiple spinners with a string array that has 3 items called "70","80" and "90". After the user selects these different spinner items I want to be able to sum up all of the items which the user has selected and display the total in a textview.For example a user selects "70" from one spinner and "70" from another, a textview will show the total 140. How can I do this?
public class FragmentCalc3 extends Fragment{
Context context;
TextView Results;
public static FragmentCalc3 newInstance()
{
FragmentCalc3 fragment = new FragmentCalc3();
return fragment;
}
public FragmentCalc3() {}
// Required empty public constructor
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_calculator3, container, false);
Results = (TextView) rootView.findViewById(R.id.Results);
context = container.getContext();
final Spinner spinner1 = (Spinner) rootView.findViewById(R.id.TestSpinner2);
ArrayAdapter<CharSequence> adapter1 = ArrayAdapter.createFromResource(context, R.array.GradeTest, android.R.layout.simple_spinner_item);
adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // Specify the layout to use when the list of choices appears
spinner1.setAdapter(adapter1); // Apply the adapter to the spinner
final Spinner spinner2 = (Spinner) rootView.findViewById(R.id.TestSpinner1);
ArrayAdapter<CharSequence> adapter2 = ArrayAdapter.createFromResource(context, R.array.GradeTest, android.R.layout.simple_spinner_item);
adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // Specify the layout to use when the list of choices appears
spinner2.setAdapter(adapter2); // Apply the adapter to the spinner
spinner2.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
int spinner2Value = Integer.parseInt(spinner2.getSelectedItem().toString());
int spinner1Value = Integer.parseInt(spinner1.getSelectedItem().toString());
int Results = spinner2Value + spinner1Value;
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
return rootView;
}
}
If you have two spinners spinner2 and spinner1, And you want to get result when item of spinner2 is selected then simply do like this,
spinner2.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
int spinner2Value = Integer.parseInt(spinner2.getSelectedItem().toString()); //Add try catch block if necessary
int spinner1Value = Integer.parseInt(spinner1.getSelectedItem().toString());
int yourResult = spinner2Value + spinner1Value; //Result
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
//Do nothing
}
});
I am working on an app for school where I have to crate a shopping list and when I select one list I should get a new activity with the products on that list. Now my problem is that when I try to get the clicked element in the listView and then put the products on that list in the listview of the new activity I get a null pointer exception on a textview.
This is the textview that gets the exception
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="20dp"
android:textColor="#236B8E"
android:layout_marginTop="20dp"
android:id="#+id/products_on_list"/>
</LinearLayout>
This is the listView in my new activity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/shopping_list_details">
</ListView>
</LinearLayout>
Here's the java code for the new activity:
public class DisplayShoppingListDetailsActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//defines the activity layout
setContentView(R.layout.shopping_list_details);
ListView listView = (ListView) findViewById(R.id.listView_shopping_lists);
Intent intent = getIntent();
String name = intent.getStringExtra("list");
ProductsOnListAdapter ad = new ProductsOnListAdapter(this, -1, Service.getService().getProductsOnList(name));
listView.setAdapter(ad);
}
}
this is the fragment where I have the list of shopping lists. Here is where I create the Intent to the new activity:
public class Fragment1 extends Fragment {
public Fragment1() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment1, container, false);
final ListView listView = (ListView) rootView.findViewById(R.id.listView_shopping_lists);
// get data from the table by the ListAdapter
ShoppingListAdapter listAdapter = new ShoppingListAdapter(getActivity(), -1, Service.getService().getShoppingLists());
listView.setAdapter(listAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// selected item
// HERE IS THE PROBLEM
// I have tried to use rootView instead of view
TextView textview = (TextView) view.findViewById(R.id.products_on_list);
String list = textview.getText().toString();
// Launching new Activity on selecting single List Item
Intent intent = new Intent(getActivity(), DisplayShoppingListDetailsActivity.class);
// sending data to new activity
intent.putExtra("list", list);
startActivity(intent);
}
});
//System.out.println("Test: " + Storage.getStorage().getShopingLists());
return rootView;
}
}
And this is the exception:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.CharSequence android.widget.TextView.getText()' on a null object reference
at com.gnirt69.slidingmenuexample.fragment.Fragment1$1.onItemClick(Fragment1.java:44)
the ShoppingListAdapter:
#Override
public View getView(int position, View convertView, final ViewGroup parent){
// Get the data item for this position
//final ShoppingList list = getItem(position);
ViewHolder holder;
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = View.inflate(getContext(), R.layout.items_lists_row, null);
//set up the viewHolder
holder = new ViewHolder();
holder.shoppingListTextView = (TextView) convertView.findViewById(R.id.textView1);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
// get the reference to the specific item
final ShoppingList list = getItem(position);
//TextView tv = (TextView) convertView.findViewById(R.id.textView1);
//manipulate the view
holder.shoppingListTextView.setText(list.getName());
return convertView;
}
public static class ViewHolder {
private TextView shoppingListTextView;
}
=======EDIT after solving the null pointer=======
Now it opens the new activity but it is empty, it doesn't populate the listview. I am trying yo figure out where exactly I am doing something wrong.
This is my fragment:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment1, container, false);
final ListView listView = (ListView) rootView.findViewById(R.id.listView_shopping_lists);
// get data from the table by the ListAdapter
final ShoppingListAdapter listAdapter = new ShoppingListAdapter(getActivity(), -1, Service.getService().getShoppingLists());
listView.setAdapter(listAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
ShoppingList shoppingList = listAdapter.getItem(position);
// selected item
TextView textview = (TextView) rootView.findViewById(R.id.products_on_list);
String list = textview.getText().toString();
// Launching new Activity on selecting single List Item
Intent intent = new Intent(getActivity(), DisplayShoppingListDetailsActivity.class);
// sending data to new activity
intent.putExtra("list", list);
//System.out.println(shoppingList.getProductsOnList());
startActivity(intent);
}
});
//System.out.println("Test: " + Storage.getStorage().getShopingLists());
return rootView;
}
The new activity that should display the products on the clicked list but it doesn't:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//defines the activity layout
setContentView(R.layout.shopping_list_details);
ListView listView = (ListView) findViewById(R.id.shopping_list_details);
Intent intent = getIntent();
String name = intent.getStringExtra("list");
ProductsOnListAdapter ad = new ProductsOnListAdapter(this, -1, Service.getService().getProductsOnList(name));
listView.setAdapter(ad);
}
And the adapter:
#Override
public View getView(int position, View convertView, final ViewGroup parent){
// Get the data item for this position
//final ShoppingList list = getItem(position);
ViewHolder holder;
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = View.inflate(getContext(), R.layout.shopping_list_details, null);
//set up the viewHolder
holder = new ViewHolder();
holder.productsTextView = (TextView) convertView.findViewById(R.id.products_on_list);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
// get the reference to the specific item
final ProductOnList product = getItem(position);
//TextView tv = (TextView) convertView.findViewById(R.id.textView1);
//manipulate the view
holder.productsTextView.setText(product.toString());
return convertView;
}
public static class ViewHolder {
private TextView productsTextView;
}
I think the Problem is that you want to call a Textview from layout
setContentView(R.layout.shopping_list_details);
But your fragment uses the layout
final View rootView = inflater.inflate(R.layout.fragment1, container, false);
You can work around this issue by passing the TextView to your Fragment from the Main or change your xml Layout
You can test if this is true by adding a textview with the same id to the fragment1 layout.
You are referring to the same ListView R.id.listView_shopping_lists in your new Activity and your Fragment, you never target shopping_list_details in your Activity layout file which will contain each item, therefore the TextView is null.