问题
I am implementing spinner in a list view (Multiple Spinners) for different products with their images on left and prices on right. User has choice to select number (quantity) of each product.
This work is going in a Class that extends from BaseAdapter according to my needs. In getView of the spinner I set the spinner view.
Now I want:
1) when the user select an Item in a Spinner, the price of that item is calculated as total and the TextView text on the right is set to that total price. Now this is working well, but when I scroll up the list, the Spinner changes its value to the old one (i.e., the value at position 0) not the new one total.
2) The other thing i want to do is to keep all these values that came from different spinners in an array, so that at the end all different spinners values are further calculated as total (at first i was calculating the single product values, say the price of that product is 50$ and the user selected that he want 20 pieces of that product so totall=20x50 ).
3) And one other thing i want is to get the number of items selected in one spinner. And in the same way to keep these numbers of each spinner in another array, so that at the end these all are calculated as total number of all products.
Below is the image and sorry as my question gone too long, but i really want to solve this out. And if you want more things from me to post please do tell me.
When I select Items
When I scroll the screen all values in spinners and the prices in the text views reset to initial position
Here is my code
public class Base_Adapter extends BaseAdapter
{
ImageView image;
TextView name, price;
Context context ;
ArrayList<ItemDetails> IDetails; //The item class which have methods and fields
RelativeLayout R_Layout;
Activity activit;
public Base_Adapter(Context context , ArrayList<ItemDetails> li)
{
this.context = context;
IDetails = li;
}
public void setLayout(Activity activity, RelativeLayout layout){
R_Layout = layout;
this.activit = activity;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return IDetails.size();
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
//////// Get View For Spinner////
@Override
public View getView(final int position, View CV, ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater infleter = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(CV == null)
{
CV = infleter.inflate(R.layout.base_adapter, null);
}
final ItemDetails item = IDetails.get(position);
int min =1;
int max = Integer.parseInt(item.totall_Available());
ArrayList<String> A_list= new ArrayList<String>();
for(int i=1;i<=max;i++)
{
A_list.add("Number of Items :"+i);
}
image = (ImageView) CV.findViewById(R.id.Item_image);
name = (TextView) CV.findViewById(R.id.item_name);
price = (TextView) CV.findViewById(R.id.item_price);
final Spinner quantity = (Spinner) CV.findViewById(R.id.items);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, R.layout.spinner_textview, A_list);
quantity.setAdapter(adapter);
//String selectedItem = (String) quantity.getSelectedItem();
name.setText(item.name());
/// ItemClick/////
quantity.setOnItemSelectedListener(new OnItemSelectedListener()
{
public void onItemSelected(AdapterView<?> arg0, View arg1, int i, long arg3)
{
if(i>0){
float cal=Float.parseFloat(item.Fisrtprise());
float cal3=cal*i;
price.setText(""+String.format("%.2f", cal3).replace(".", ","));
String s = Float.toString(cal3);
item.Totalprice=s;
}
else{
price.setText(""+String.format("%.2f", Float.parseFloat(item.Fisrtprise())).replace(".", ","));
}
}
public void onNothingSelected(AdapterView<?> arg0){
}
});
return CV;
}
And this is the IDetails Class
@SuppressWarnings("serial")
public class IDetails implements Serializable
{
ContentValues colmnValues;
private int no_of_items;
public float Totalprice;
public IDetails(ContentValues values )
{
colmnValues = values;
}
public String title() {
return getValue(colmnValues.get("title"));
}
public void setNo_of_items(int no_of_items) {
this.no_of_items = no_of_items;
}
public int getNo_of_items() {
return no_of_items;
}
public void setTotalprice(float Totalprice) {
this.Totalprice = Totalprice;
}
public float getTotalprice() {
return Totalprice;
}
public String imageUrl() {
return getValue(colmnValues.get("imageUrl"));
}
public String pprice() {
return getValue(colmnValues.get("Realprice"));
}
public String stock() {
return getValue(colmnValues.get("stock"));
}
private String getValue(Object obj){
if(obj == null){
return "";
}
return (String) obj;
}
}
回答1:
I just update your code without creating new. First I will answer the three questions.
- The spinners are resetting after scrolled because the adapter call
getView()method and they are initializing to default value again. To avoid this and get back your previously selected values, what you have to do is save them in a map and assign back. In following code "selectedItem" is the map I used to store selected amounts for each spinner. - To get total amount you can use another map which is used to store
total price of each spinner. In the following code I used
"
totalPrices" for it. InsideonItemSelected()we can put total amount for specific spinner. Inside the onclick() method of "BUY" button you can access this map by callinggetTotalPrice()method is adapter class. - This is quiet easy. We don't have to get separate array. We can get
this information using "
selectedItem" map which used to store selected values of spinners. Same as the total price, you can get this map usinggetTotalItems().
Also in your price calculation inside onItemSelected() method you used "i" to multiply the item price. It should be (i+1). Because "i" is the position of the list in spinner. It starts from 0.
This is the Base_Adapter class
public class Base_Adapter extends BaseAdapter{
ImageView image;
TextView name, price;
private HashMap<Integer,Integer> selectedItem=new HashMap<Integer, Integer>();
private HashMap<Integer, String> totalPrices=new HashMap<Integer, String>();
Context context ;
ArrayList<ItemDetails> IDetails; //The item class which have methods and fields
RelativeLayout R_Layout;
Activity activit;
public Base_Adapter(Context context , ArrayList<ItemDetails> li) {
// TODO Auto-generated constructor stub
this.context = context;
IDetails = li;
}
public void setLayout(Activity activity, RelativeLayout layout){
R_Layout = layout;
this.activit = activity;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return IDetails.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
public HashMap<Integer,Integer> getTotalItems(){
return selectedItem;
}
public HashMap<Integer, String> getTotalPrice(){
return totalPrices;
}
//////// Get View For Spinner////
@Override
public View getView(final int position, View CV, ViewGroup parent) {
// TODO Auto-generated method stub
final ItemDetails item = IDetails.get(position);
int min =1;
int max = Integer.parseInt(item.stock());
LayoutInflater inflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView=inflater.inflate(R.layout.base_adapter, parent,false);
ArrayList<String> A_list= new ArrayList<String>();
for(int i=1;i<=max;i++)
{
A_list.add("Number of Items :"+i);
}
ImageView image=(ImageView) rowView.findViewById(R.id.item_image);
TextView nameTextView=(TextView) rowView.findViewById(R.id.item_name);
nameTextView.setText(item.title());
final TextView price=(TextView) rowView.findViewById(R.id.item_price);
Spinner quantity=(Spinner) rowView.findViewById(R.id.items);
ArrayAdapter<String > quatity=new ArrayAdapter<String>(context, R.layout.spinner_textview, R.id.item_list, A_list);
quantity.setAdapter(quatity);
if(selectedItem.get(position) != null){
//This should call after setAdapter
quantity.setSelection(selectedItem.get(position));
}
quantity.setOnItemSelectedListener(new OnItemSelectedListener()
{
public void onItemSelected(AdapterView<?> arg0, View arg1, int i, long arg3)
{
if(i>0){
selectedItem.put(position, i);
i=i+1;
float cal=Float.parseFloat(item.price());
float cal3=cal*i;
price.setText(""+String.format("%.2f", cal3).replace(".", ","));
item.Totalprice= cal3;
}
else{
price.setText(""+String.format("%.2f", Float.parseFloat(item.price())).replace(".", ","));
}
totalPrices.put(position, price.getText().toString());
}
public void onNothingSelected(AdapterView<?> arg0){
}
});
return rowView;
}
}
So inside your activity class implement onclick method for the "BUY" button.
public void getTotal(View view){
HashMap<Integer, Integer>totalItems=adapter.getTotalItems();
HashMap<Integer, String> totalPrices=adapter.getTotalPrice();
for(int i=0;i<totalItems.size();i++){
if(totalItems.get(i) != null){
System.out.println("Spinner No"+(i+1)+"Items :"+(totalItems.get(i)+1));
System.out.println("Spinner No "+(i+1)+"total price "+totalPrices.get(i));
}else{
System.out.println("Spinner No"+(i+1)+"Items : 1");
}
}
回答2:
U need something like badge(selected quantity) * the mrp which will give total amount
For reference https://developer.android.com/training/contacts-provider/display-contact-badge.html
回答3:
Brace yourself, this answer got long.
You already have a class, IDetails, that describes the items up for sale. I'll suggest a slightly different approach, but if you don't like it, jump to The Adapter-section. I will however use my altered models throughout this answer, as they make stuff easier for some of your questions.
The models
Create a base class that describes an item. We'll make this class abstract and extend on it to describe the individual items you sell.
public abstract class ShoppingItem {
/* You can add more fields here, for example an image */
protected String title;
protected String description;
protected int cost;
// Each object keeps track of how many of itself is being bought
protected int numberBought = 1;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getCost() {
return cost;
}
public void setCost(int cost) {
this.cost = cost;
}
public int getNumberBought() {
return numberBought;
}
public void setNumberBought(int numberBought) {
this.numberBought = numberBought;
}
}
Individual items can now easily be created:
public class Banana extends ShoppingItem {
public Banana() {
this.title = "Banana";
this.description = "A tasty banana";
this.cost = 100;
}
}
public class Apple extends ShoppingItem {
public Apple() {
this.title = "Apple";
this.description = "A fresh apple";
this.cost = 200;
}
}
The Adapter
Now that we have the models all sorted out, how do we populate a ListView with them in the most effienct way? With a custom Adapter, just like you did. We'll fix the spinners resetting when scrolling, and we will also add some nifty performance enhancements.
public class ShoppingAdapter extends ArrayAdapter<ShoppingItem> {
// We use this LayoutInflater to inflate the xml for each row in the list
private LayoutInflater mInflater;
// This is the strings that will populate the spinners
// Can be moved to res/values/string-array.xml to prevent hardcoded strings
private String[] spinnerArray = new String[] { "No. items: 1",
"No. items: 2",
"No. items: 3",
"No. items: 4"};
public ShoppingAdapter(Context context, int resource, ArrayList<ShoppingItem> objects) {
super(context, 0, objects);
// Initialize the declared LayoutInflater
mInflater = LayoutInflater.from(context);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// This is a simple reference holding class, so we don't have to call
// findViewById() every time getView() is called. Improved performance :)
ViewHolder holder = null;
if(convertView == null) {
// If convertView is null, then we don't have a view to place
// our data in. We have to inflate one ourself
convertView = mInflater.inflate(R.layout.list_item, null);
// Store a reference to the Spinner and the TextView in
// the ViewHolder object
holder = new ViewHolder();
holder.spinner = (Spinner) convertView.findViewById(R.id.spinner);
holder.textView = (TextView) convertView.findViewById(R.id.total);
// Attach the ViewHolder object to convertView, as a tag
convertView.setTag(holder);
}
else {
// If convertView is non-null then we can fetch the ViewHolder object
// we stored in the tag earlier. We now have references to both the Spinner
// and TextView, through the ViewHolder object.
holder = (ViewHolder) convertView.getTag();
}
// If the holder is non-null, we are good to go!
if(holder != null) {
// Fetch the item from the underlying ArrayList
final ShoppingItem item = getItem(position);
// We need this to be final, so we can access it inside the
// onItemSelected()-callback
final TextView textview = holder.textView;
// Populate the Spinner
holder.spinner.setAdapter(new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item, spinnerArray));
// Add a callback when an item is selected in the Spinner
holder.spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View v, int pos, long id) {
// Spinner position is 0-based, so we have to increment
// by one
item.setNumberBought(pos + 1);
// Update the total amount in the TextView
textview.setText(Integer.toString(item.getCost() * item.getNumberBought()));
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {} // We don't care
});
// Set the spinner to the correct position
// By asking the underlying item how many is bought,
// the spinner will always show the correct number.
holder.spinner.setSelection(getItem(position).getNumberBought()-1);
}
return convertView;
}
// This guys job is to hold references to the
// views we need to access in each row
private static class ViewHolder {
public Spinner spinner;
public TextView textView;
}
}
How to use it
public class MainActivity extends ListActivity {
private ShoppingAdapter mAdapter;
private ArrayList<ShoppingItem> items;
@SuppressWarnings("unchecked")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// If savedInstanceState is null, then we have a "fresh" start.
// Create the
if(savedInstanceState == null) {
items = new ArrayList<ShoppingItem>();
items.add(new Banana());
items.add(new Apple());
items.add(new Banana());
items.add(new Apple());
items.add(new Banana());
items.add(new Apple());
items.add(new Banana());
}
// If savedInstanceState is non-null, we should be able to fetch
// the list of items
else {
items = (ArrayList<ShoppingItem>) savedInstanceState.getSerializable("items");
}
mAdapter = new ShoppingAdapter(this, 0, items);
getListView().setAdapter(mAdapter);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// We have to keep our ListView persistent through screen rotations.
// Lets store the list of items in the "savedInstanceState" Bundle.
outState.putSerializable("items", items);
}
}
Getting all the metadata you wanted, like total cost, total number of products, etc is easy.
@Override
public void onClick(View v) {
int totalCost = 0;
int numBananas = 0;
int numApples = 0;
int totalNum = mItems.size();
for(ShoppingItem item : mItems) {
int numberBought = item.getNumberBought();
totalCost += item.getCost() * numberBought;
if(item instanceof Banana) {
numBananas += numberBought;
}
else if(item instanceof Apple) {
numApples += numberBought;
}
// etc, etc
}
}
来源:https://stackoverflow.com/questions/21709115/how-to-get-the-number-of-items-in-multiple-spinner-view-and-calculate-the-total