I have a list view where each row displays the name of some inventory item, its quantity available, and a spinner to select the amount of the item to buy (when clicking make purchase at the bottom of the page, the selected amount of each spinner is grabbed and processed).
I currently have a loop that iterates over the rows and grabs the spinner by its identifier. It uses the position of the row to access another array that contains the corresponding qty of the item show in this position. It uses this qty as a stopping point for another nested loop that creates an ArrayList of numbers up to the given qty (so a user cannot select more than what is available). The ArrayList is then popped into a custom ArrayAdapter as the data field but for some reason the ArrayAdapter is not populating the spinner. What's missing??
Heres the relevant code
public class PlaceOrder extends Activity {
ArrayList<Item> items;
ArrayList<Customer> customers;
int position;
ListView orderList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_place_order);
Intent data = getIntent();
items = data.getParcelableArrayListExtra("items");
customers = data.getParcelableArrayListExtra("customers");
position = data.getIntExtra("position", 0);
orderList = (ListView) findViewById(R.id.purchaseList);
PurchasedItemAdapter itemAdapter = new PurchasedItemAdapter(this, R.layout.purchase_table_row, items);
orderList.setAdapter(itemAdapter);
for (int i = 0; i < orderList.getCount(); i++) {
View view = orderList.getAdapter().getView(i, null, null);
Spinner spinner = (Spinner) view.findViewById(R.id.purchase_table_spinner);
int stop = items.get(i).qtyAvailable;
ArrayList<String> stringList = new ArrayList<String>();
for (int k = 0; k <= stop; k++) {
stringList.add(String.format("%d", k));
}
SpinnerAdapter spinnerAdapter = new SpinnerAdapter(this, R.layout.simple_spinner_item, stringList);
spinner.setAdapter(spinnerAdapter);
}
}
Adapter Class...
public class SpinnerAdapter extends ArrayAdapter<String> {
Context context;
int layoutResourceId;
ArrayList<String> data = null;
public SpinnerAdapter (Context context, int layoutResourceId, ArrayList<String> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder = null;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ViewHolder();
holder.qty = (TextView)row.findViewById(R.id.simple_spinner_text);
row.setTag(holder);
} else {
holder = (ViewHolder)row.getTag();
}
holder.qty.setText(data.get(position));
return row;
}
static class ViewHolder {
TextView qty;
}
}
Listview Adapter..
public class PurchasedItemAdapter extends ArrayAdapter<Item> {
Context context;
int layoutResourceId;
ArrayList<Item> data = null;
public PurchasedItemAdapter(Context context, int layoutResourceId, ArrayList<Item> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ItemHolder holder = null;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ItemHolder();
holder.name = (TextView)row.findViewById(R.id.purchase_table_itemName);
holder.qty = (TextView)row.findViewById(R.id.purchase_table_qty);
row.setTag(holder);
} else {
holder = (ItemHolder)row.getTag();
}
Item item = data.get(position);
holder.name.setText(item.name);
holder.qty.setText(String.format("%d", item.qtyAvailable));
return row;
}
static class ItemHolder {
TextView name;
TextView qty;
}
}
If PurchasedItemAdapter is your custom list adapter spinnerAdapter for each row(if the spinner is not same for each row) is suitable to set inside the PurchasedItemAdapter class or at least it is better to set spinner adapter before PurchasedItemAdapter
" the selected amount of each spinner is grabbed and processed" so each row of your list has a spinner why don't you set it inside PurchaseItemAdapter and add a spinner item in view Holder class as well...I would do so
Related
I have done the code but it appears the Search is not working
public class MainActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {
ListView lv;
SearchView searchView;
ArrayAdapter<String> adapter;
String[] apptitle = {"†orch", "Quiz It!"};
String[] inf = {"click for info", "click for info"};
int[] img = {R.drawable.ic_launcher, R.drawable.ic_launcher};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
lv = (ListView) findViewById(R.id.idlistview);
searchView = (SearchView) findViewById(R.id.idsearch);
Adapterim adapter = new Adapterim(getApplicationContext(), apptitle, inf, img);
lv.setAdapter(adapter);
/*adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, appTitle);
lv.setAdapter(adapter);*/
searchView.setOnQueryTextListener(this);
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
}
// ArrayAdapter extends, Let's create class
class Adapterim extends ArrayAdapter<String> {
//For the information we need for our content
//Create array variable
int[] img = {};
String[] apptitle = {};
String[] inf = {};
//Context and layoutinflater as required
//Let's create them
Context c;
LayoutInflater inflater;
//The parameters of the generated method
public Adapterim(Context context, String[] apptitle, String[] inf, int[] img) {
//Values to be entered into the super method
//
super(context, R.layout.listview_class, apptitle);
// Equalize the parameters to the variables in this class
this.img = img;
this.apptitle = apptitle;
this.inf = inf;
this.c = context;
}
// Let's create our inner class and
// create our components
public class Viewholder {
TextView attv;
TextView inftv;
ImageView imgim;
}
//With this automatic method, each element in the array can be edited one by one
//We add data to the components in ListView
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.listview_class, null, true);
}
// Create an object from our class we created
final Viewholder holder = new Viewholder();
// And the components we create in our inner structure
//I sync with the components in the layout
holder.attv = (TextView) convertView.findViewById(R.id.custom_textView);
holder.inftv = (TextView) convertView.findViewById(R.id.custom_textView2);
holder.imgim = (ImageView) convertView.findViewById(R.id.custom_imageView);
//In order to assign the array elements as data for each component
//Assign position value to our arrays
//And set the values of our components
holder.imgim.setImageResource(img[position]);
holder.attv.setText(apptitle[position]);
holder.inftv.setText(inf[position]);
//It must be a return value and I will return View
return convertView;
}
}
What is want is to update total number in textview in one activity. i have a custom adapter which calls Arraylist in this activity then populates in listview, this adapter also has image view which removes the list item and does notifydatasetchanged().
this is my customadapter
private ArrayList<DataModel> dataSet;
Context mContext;
private static class ViewHolder {
TextView txtName;
TextView txtType;
Button remove;
}
public CustomAdapterForData(ArrayList<DataModel> data, Context context) {
super(context, R.layout.fields, data);
this.dataSet = data;
this.mContext=context;
}
#Override
public void onClick(View view) {
int position = (Integer) view.getTag();
Object object = getItem(position);
DataModel dataModel = (DataModel) object;
switch (view.getId())
{
case R.id.btnRemove:
remove(dataModel);
// dataSet.remove(position);
//dataSet.remove(position);
notifyDataSetChanged();
break;
}
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
DataModel dataModel = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
final View result;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.fields, parent, false);
viewHolder.txtName = (TextView) convertView.findViewById(R.id.fieldName);
viewHolder.txtType = (TextView) convertView.findViewById(R.id.tvPrize);
viewHolder.remove = (Button) convertView.findViewById(R.id.btnRemove);
result=convertView;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
result=convertView;
}
viewHolder.txtName.setText(dataModel.getFieldName());
viewHolder.txtType.setText(dataModel.getType());
viewHolder.remove.setOnClickListener(this);
viewHolder.remove.setTag(position);
return convertView;
}
after that this is my onstart()
protected void onStart() {
//if ((dataModels.size()!=0)){
ListView listView = (ListView) findViewById(R.id.listView);
adapter = new CustomAdapterForData(dataModels, getApplicationContext());
listView.setAdapter(adapter);
dataModelsnew = dataModels;
TextView tv = (TextView) findViewById(R.id.textViewTotal);
double sum = 0;
for (int i = 0 ; i < dataModelsnew.size(); i++){
sum = sum + dataModelsnew.get(i).getPrize();
}
tv.setText("Total : " + String.valueOf(Math.round(sum)*100d/100d));
//}
super.onStart();
}
what i want is populate latest value in textview which is sum of double (one element of ArrayList).Please help me to resolve this.
Thanks in advance. The variable i want to update after i remove something from list view otherwise it is working fine.
You can use DataSetObservers to detect any changes in your data:
final TextView tv = (TextView) findViewById(R.id.textViewTotal);
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
double sum = 0;
for (int i = 0 ; i < dataModels.size(); i++){
sum = sum + dataModels.get(i).getPrize();
}
tv.setText("Total : " + String.valueOf(Math.round(sum)*100d/100d));
}
});
I've been attempting to upgrade an old app I made in college, including adding a listview to show data from Last.FM. The idea is having a main text with subtext under it, but the adapter I put together just isn't working. I've tried a good number of options, and the most recent is giving me a "Attempt to invoke virtual method on a null object reference" error, a previous try got a "Cannot cast Activity to Application" error.
Relevant code sections:
Main Activity adapter section:
ListView lv;
final Dialog dialog = new Dialog(MainActivity.this);
dialog.setContentView(R.layout.summarylayout);
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT);
lv = (ListView) dialog.findViewById(R.id.itemList); //Listview name
artistAdapter = new itemAdapter(getApplicationContext(), //Changed from ArrayAdapter<Item>
R.layout.custom_listview, //R.layout.custom_listview if itemAdapter works
result.toArray(new Item[] {}));
lv.setAdapter(artistAdapter);
lv.setOnItemClickListener(new MyOIListener());
Button closeButton = (Button) dialog
.findViewById(R.id.closeBtn);
// if button is clicked, close the custom dialog
closeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
tracks = false;
dialog.dismiss();
}
});
The custom Adapter itself (Commented sections are previous attempts):
public class itemAdapter extends ArrayAdapter<Item>{
Context context;
int layoutResourceId;
Item data[] = null;
public itemAdapter(Context context, int layoutResourceId, Item[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
// ItemHolder holder = null;
Item rowIn = new Item();
TextView main;
TextView sub;
if(row == null)
{
//LayoutInflater inflater = ((Application)context).getLayoutInflater();
//row = inflater.inflate(layoutResourceId, parent, false);
//row = LayoutInflater.from(getActivity()).inflate(R.layout.custom_listview, parent, false);
LayoutInflater inflater = LayoutInflater.from(this.getContext());
row = inflater.inflate(layoutResourceId, parent, false);
//holder = new ItemHolder();
//rowIn = new Item();
}
else
{
rowIn = (Item) row.getTag();
}
main = (TextView)row.findViewById(R.id.mainText);
sub = (TextView)row.findViewById(R.id.subText);
row.setTag(rowIn);
Item temp = data[position];
main.setText(temp.getTitle());
sub.setText(temp.getExtra());
return row;
}
/* static class ItemHolder
{
TextView mainText;
TextView subText;
}*/
}
The "Item" class is simply a holder for text/URLs parsed from the Last.FM api request.
I realize this is a question asked often, but 3 days of attempts and searching hasn't helped me out much. Any help would be appreciated
You're passnig the applicationContext to your adapter. Pass your Activity by:
artistAdapter = new itemAdapter(MainActivity.this, //Changed from ArrayAdapter<Item>
R.layout.custom_listview, //R.layout.custom_listview if itemAdapter works
result.toArray(new Item[] {}));
Your getView method was wrong, actually you will face a null variable there when getting the data from the tag.
This one should work for you, it is using ViewHolder Pattern
public class itemAdapter extends ArrayAdapter<Item> {
Context context;
int layoutResourceId;
Item data[] = null;
public itemAdapter(Context context, int layoutResourceId, Item[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ItemHolder holder = null;
if (convertView == null) {
//LayoutInflater inflater = ((Application)context).getLayoutInflater();
//row = inflater.inflate(layoutResourceId, parent, false);
//row = LayoutInflater.from(getActivity()).inflate(R.layout.custom_listview, parent, false);
LayoutInflater inflater = ((Activity) this.context).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
holder = new ItemHolder();
holder.mainText = row.findViewById(R.id.mainText);
holder.subText = row.findViewById(R.id.subText);
convertView.setTag(holder);
} else {
holder = (ItemHolder) convertView.getTag();
}
Item temp = data[position];
if(temp != null) {
holder.mainText.setText(temp.getTitle());
holder.subText.setText(temp.getExtra());
}
return convertView;
}
static class ItemHolder {
TextView mainText;
TextView subText;
}
}
And as #vinitius said, pass your Activity context to the adapter.
I try to change background color of a button in item of my listView, but when I try to change the background, the background change each 9 items.
When I try to change the orientation of my phone, the background change each 5 items...
---IMAGE TO UNDERSTAND:
http://image.noelshack.com/fichiers/2014/09/1393436440-problem.png
I don't understand, is so strange.
I have an Adapter created.
Java.java (Not my adapter file)
public void clickPresent(View v)
{
v.setBackgroundColor(Color.BLUE);
}
public void drawStudentsInListView()
{
for (int i = 0; i < this.listStudents.size(); i++)
{
Log.e("STUDENT", this.listStudents.get(i)._firstName);
}
if (listStudents.size() > 0)
{
Student[] weather_data;
weather_data = new Student[listStudents.size()];
for (int i = 0; i < listStudents.size(); i++)
{
weather_data[i] = new Student(listStudents.get(i)._firstName, listStudents.get(i)._lastName);
Log.e("Count nbr student: ", "i = " + i);
}
WeatherAdapter adapter = new WeatherAdapter(this, R.layout.listview_item_row, weather_data);
listView1 = (ListView)findViewById(R.id.listView1);
listView1.setAdapter(adapter);
}
}
listview_item_row.xml
<Button
android:layout_width="100dp"
android:layout_height="30dp"
android:background="#009857"
android:layout_marginLeft="10dp"
android:textColor="#ffffff"
android:text="OK"
android:id="#+id/buttonPresent"
android:onClick="clickPresent" />
Adapter.java
public class WeatherAdapter extends ArrayAdapter<Student>
{
Context context;
int layoutResourceId;
Student data[] = null;
public WeatherAdapter(Context context, int layoutResourceId, Student[] data)
{
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
WeatherHolder holder = null;
if (row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new WeatherHolder();
holder.firstName = (TextView)row.findViewById(R.id.textFirstName);
holder.lastName = (TextView)row.findViewById(R.id.textLastName);
row.setTag(holder);
}
else
{
holder = (WeatherHolder)row.getTag();
}
Student weather = data[position];
holder.firstName.setText(weather._firstName);
holder.lastName.setText(weather._lastName);
return row;
}
static class WeatherHolder
{
TextView firstName;
TextView lastName;
}
}
I don't understand what the problem is :/
Thanks,
To improve performance, ListView uses old views to inflate new ones when you scroll, that's why you see a repeated action in other ones.
To fix your problem, i recommand you to set a boolean variable as Tag for the current item button.
Given that, your row item contains (firstName, lastname), add a new attribut Button like that.
static class WeatherHolder
{
TextView firstName;
TextView lastName;
Button button
}
init it at your GetView as you do for other items, and then when you retreive Student details, Check if the button has a tag equals to True (=> that means already clicked)
And in your clickPresent method just set a True tag when you click and False when you unclick.
NB: if tag equals false reset the color.
public void clickPresent(View v)
{
v.setBackgroundColor(Color.BLUE);
v.setTag(true);
}
For my android application i'm using the ViewHolder pattern.
Whenever i click on an imageview in my listview the row get updated but other rows are also getting updated.
Whenever i click the "like" button other images also receive the image that the are liked by the user. How is this possible?
Here is my viewholder code:
public class MyAdapter extends ArrayAdapter<MyModel> {
Context context;
int layoutResourceId;
List<MyModel> data = null;
public MyAdapter(Context context, int layoutResourceId,
List<MyModel> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
final BlockHolder holder;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new BlockHolder();
holder.imgIcon = (ImageView) row.findViewById(R.id.imgIcon);
holder.totalVotes = (TextView) row.findViewById(R.id.totalVotes);
holder.likeIcon = (ImageView) row.findViewById(R.id.likeIcon);
holder.dislikeIcon = (ImageView) row.findViewById(R.id.dislikeIcon);
holder.saveIcon = (ImageView) row.findViewById(R.id.saveIcon);
row.setTag(holder);
} else {
holder = (BlockHolder) row.getTag();
}
MyModel myBlock = data.get(position);
ImageLoader.getInstance().displayImage(myBlock.getImage(),
holder.imgIcon);
final int totalLikes = myBlock.getLikes() - myBlock.getDislikes();
holder.totalVotes.setText(totalLikes + " likes");
final ImageView like = holder.likeIcon;
holder.likeIcon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// ALSO UPDATES OTHER VIEWS...
holder.likeIcon.setBackgroundResource(R.drawable.thumbs_up_mouse);
}
});
return row;
}
private static class BlockHolder{
ImageView imgIcon;
TextView totalVotes;
ImageView dislikeIcon;
ImageView likeIcon;
ImageView saveIcon;
}