I have a simple table layout that I want to populate just by initialising a specific type
of object in my onCreate method. First off this is the layout I have
jobs_table.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout android:id="#+id/Jobs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="*"
xmlns:android="http://schemas.android.com/apk/res/android">
<TableRow android:id="#+id/JobRow" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:id="#+id/JobID" android:layout_column="1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#color/black"></TextView>
<TextView android:id="#+id/JobStatus" android:layout_column="2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#color/black"></TextView>
<TextView android:id="#+id/Customer" android:layout_column="3" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#color/black"></TextView>
<TextView android:id="#+id/Department" android:layout_column="4" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#color/black"></TextView>
<TextView android:id="#+id/DocType" android:layout_column="5" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#color/black"></TextView>
</TableRow>
</TableLayout>
And the activity
package com.producermobile;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TableLayout;
import com.producermobile.jobs.ProducerJobRows;
public class JobRowsActivity extends Activity {
private BatchingJobRows jobRows;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.jobs_table);
jobRows = new BatchingJobRows(this);
}
}
Now the idea will be when I create my jobRows the data for the table will be loaded by the BatchingJobRows object, which should hopefully then be available to my activity. I don't have a way of checking this at the mo though so I'm not sure if the concept is right (my main worry is the while loop which is adding rows to the table).
Anyway here's a simplified version of what's happening in the BatchingJobRows.
package com.producermobile.jobs;
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import com.producermobile.R;
public class BatchingJobRows {
private TableLayout table;
private View tableView;
private Context context;
private HashMap<String,ArrayList<String>> jobs;
private ArrayList<String> jobsVals;
public BatchingJobRows(Context context) {
this.context = context;
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
tableView = inflater.inflate(R.layout.jobs_table, null);
table = (TableLayout) tableView.findViewById(R.id.Jobs);
jobVals = new ArrayList<String>();
jobVals.add("HELD");
jobVals.add("DELL");
jobVals.add("PRINT");
jobVals.add("STATEMENT");
jobs = new HashMap<String,ArrayList<String>>();
jobs.put("012345",jobVals);
jobs.put("123456",jobVals);
this.setRows();
}
public void setRows() {
Iterator<String> keys = jobs.keySet().iterator();
while(keys.hasNext()) {
//Init Objects
TableRow row = (TableRow) TableView.findViewById(R.id.JobRow);
TextView jobid = (TextView) tableView.findViewById(R.id.JobID);
TextView jobstatus = (TextView) tableView.findViewById(R.id.JobStatus);
TextView customer = (TextView) tableView.findViewById(R.id.Customer);
TextView department = (TextView) tableView.findViewById(R.id.Department);
TextView doctype = (TextView) tableView.findViewById(R.id.DocType);
String key = keys.next();
jobid.setText(key);
jobstatus.setText(jobs.get(key).get(0));
customer.setText(jobs.get(key).get(1));
department.setText(jobs.get(key).get(2));
doctype.setText(jobs.get(key).get(3));
row.addView(jobid);
row.addView(jobstatus);
row.addView(customer);
row.addView(department);
row.addView(doctype);
table.addView(row);
}
}
}
Well this is not a direct answer to your question but what I think you should do is create a list activity, and move this functionality down into a ListAdapter of some type. We can help you with question on how to set that up. Its probably easier than the route you are going, and more familiar to people on this board. So i would recommend taking the conventional approach on this. Use ListActivity, and ListAdapter Base or Cursor depending on your needs.
Related
i have one list view with two text views inside it, one edit text that is in the same activity but not in the list view and two buttons one to add to the list view and the other to delete from it.
how to add integers to the first text view, the sum of all integers to the second one, and to be from a custom adapter.
thank you.
Activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<EditText
android:id="#+id/edit_ten"
android:hint="Score"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/btn_add"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Add"/>
<Button
android:id="#+id/btn_delete"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Undo"/>
</LinearLayout>
<ListView
android:id="#+id/list_sinhvien"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
item_layout.xml
<?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"
android:orientation="horizontal">
<LinearLayout
android:orientation="vertical"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/text_ten"
android:textSize="20dp"
android:text="Score"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/text_sdt"
android:textSize="20dp"
android:text="Total"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
MainActivity.java
package com.example.addanddelete;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
ListView listSinhvien;
EditText editTen;
Button btnThem , btnSua;
ArrayList<Sinhvien> arraySinhvien;
CustomAdapter myadapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
anhxa();
arraySinhvien = new ArrayList<Sinhvien>();
myadapter = new CustomAdapter(this , R.layout.item_layout,arraySinhvien);
listSinhvien.setAdapter(myadapter);
btnSua.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final int count = myadapter.getCount();
myadapter.remove(myadapter.getItem(count -1));
myadapter.notifyDataSetChanged();
return;}});
}
private void anhxa(){
listSinhvien = (ListView)findViewById(R.id.list_sinhvien);
editTen = (EditText)findViewById(R.id.edit_ten);
btnThem = (Button)findViewById(R.id.btn_add);
btnSua = (Button)findViewById(R.id.btn_undo);
btnThem.setOnClickListener(this);
btnSua.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_add:
Toast.makeText(this, "clicked", Toast.LENGTH_SHORT).show();
String ten = editTen.getText().toString();
String sdt = editTen.getText().toString();
Sinhvien temp = new Sinhvien(R.mipmap.ic_launcher,ten , sdt);
arraySinhvien.add(temp);
myadapter.notifyDataSetChanged();
break;
}
}
}
CustomAdapter.java
package com.example.addanddelete;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
public class CustomAdapter extends ArrayAdapter {
Activity activity;
int layout;
ArrayList<Sinhvien> arrSinhVien;
public CustomAdapter(#NonNull Activity activity, int layout, #NonNull ArrayList<Sinhvien> arrSinhVien) {
super(activity, layout, arrSinhVien);
this.activity = activity;
this.layout = layout;
this.arrSinhVien = arrSinhVien;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
LayoutInflater layoutInflater = activity.getLayoutInflater();
convertView = layoutInflater.inflate(layout, null);
TextView ten = (TextView) convertView.findViewById(R.id.text_score);
TextView sdt = (TextView) convertView.findViewById(R.id.text_total);
ten.setText(arrSinhVien.get(position).getTenSinhvien());
sdt.setText(arrSinhVien.get(position).getSdtSinhvien());
return convertView;
}
}
Sinhvien.java
package com.example.addanddelete;
public class Sinhvien {
String tenSinhvien;
String sdtSinhvien;
public Sinhvien(String iclauncher,String ten, String sdt) {
}
public Sinhvien(int iclauncher,String tenSinhvien, String sdtSinhvien) {
this.tenSinhvien = tenSinhvien;
this.sdtSinhvien = sdtSinhvien;
}
public String getTenSinhvien() {
return tenSinhvien;
}
public void setTenSinhvien(String tenSinhvien) {
this.tenSinhvien = tenSinhvien;
}
public String getSdtSinhvien() {
return sdtSinhvien;
}
public void setSdtSinhvien(String sdtSinhvien) {
this.sdtSinhvien = sdtSinhvien;
}
}
The general behaviour/implementation that you've outlined in your question is very well documented. That said, I'd suggest considering utilising a RecyclerView with associated custom item view and adapter, as opposed to a ListView. There are a few reasons why I'd suggest this.
I did a little searching and found several examples that cover the general idea of your implementation. This example does a great job of illustrating how to achieve what you're seeking. The article begins by outlining some reasons to work with a RecyclerView over a ListView or GridView, then proceeds to give an in-depth run-down on how to implement a RecyclerView with custom adapter (and associated item view and item class).
At a glance, your implementation would require:
An Activity containing your RecyclerView, two Buttons (used for adding and deleting elements from the RecyclerView) and an EditText for taking user input.
A custom item View representing individual items of your RecyclerView list. This would contain the two TextView views (one for displaying the integer and the other for displaying the sum of all integers).
A custom item model Class to represent the data model for the above custom item View. This would hold an integer value and likely some logic for displaying the sum.
A custom RecyclerView adapter (which ties all of the above together). This will need to handle the task of binding data from your dataset (that grows and shrinks based on user input) to instances of your custom items that are to appear in the RecyclerView list. This adapter could also be used by your add and delete item buttons to modify the elements in the RecyclerView list.
The above is outlined in far greater depth in the link I provided earlier.
I sincerely hope that helps!
I am new to Android Studio/Development, but not programming itself. I am struggling with the syntax (as I do think it is my problem) yet I cannot find a solution anywhere on here or on Google. I have this 2nd activity named FilterActivity. FilterActivity currently has 2 TextViews. Both create dynamic CheckBoxes. Right now, I only have one doing this so I can get one right before I go onto another. Here's the issue, I click on the TextView to get the dynamically created CheckBox and it shows perfectly fine. However, clicking on it again just adds the same values until it appears to completely fill the parent via xml.
No matter what I search, what I do, it all does the same exact thing. I know, I have nothing for onCheckedChanged, but I have previously before and it did not work either. So question(s), should I not be using LinearLayout and do like a container of sorts? There will be a decently big database for the checkboxes (500+) so I was thinking I would have to implement ScrollView at some point. Also, if LinearLayout is the correct way to go, what am I doing wrong? I am just completely spinning and I know it should not be this hard.
Thank you to anyone that gives feedback!
Here's XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="xxx.AppEx.FilterActivity"
tools:layout_editor_absoluteY="81dp"
tools:showIn="#layout/activity_filter">
<View
android:id="#+id/firstView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_centerHorizontal="true" />
<View
android:id="#+id/secondView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_centerVertical="true"/>
<TextView
android:id="#+id/AllTextView"
android:clickable="true"
android:text="All"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:height="50dp"
android:layout_toLeftOf="#id/firstView"
android:layout_alignParentTop="true"
android:gravity="center"
android:textStyle="bold"
android:textAllCaps="true"/>
<TextView
android:id="#+id/DisTextView"
android:clickable="true"
android:text="Dis"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:height="50dp"
android:layout_toRightOf="#+id/firstView"
android:layout_alignParentTop="true"
android:gravity="center"
android:textStyle="bold"
android:textAllCaps="true"/>
<LinearLayout
android:id="#+id/CheckBoxLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_below="#id/secondView">
</LinearLayout>
</RelativeLayout>
Here's the main code:
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.content.Intent;
public class FilterActivity extends AppCompatActivity implements
CompoundButton.OnCheckedChangeListener {
LinearLayout CheckBoxLayout;
CheckBox checkBox;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_filter);
CheckBoxLayout = (LinearLayout) findViewById(R.id.CheckBoxLayout);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final TextView AllTextView = (TextView) findViewById(R.id.AllTextView);
AllTextView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
AllTextView.setBackgroundColor(Color.BLUE);
onAllClick();
}
});
TextView DisTextView = (TextView) findViewById(R.id.DisTextView);
DisTextView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//onAllClick();
}
});
}
public void onAllClick()
{
Intent intent = getIntent();
dummy();
}
public void dummy()
{
String[] array = new String[]
{
"Rice", "Beans"
};
LinearLayout CheckBoxLayout = (LinearLayout)findViewById(R.id.CheckBoxLayout);
for (int i = 0; i < array.length; i++)
{
CheckBox checkBox = new CheckBox(this);
checkBox.setText(array[i]);
CheckBoxLayout.addView(checkBox);
}
}
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
}
}
Update: Simpler code created and presented here, full layout XML definitions.
When trying to replace the row layout with the icon on the left by the new drawableStart attribute of the TextView element in XML layout, I can observe the following wrongly displayed last item (captured on Nexus 7):
The related code is -- MainActivity:
package cz.skil.android.tut.testtextviewdrawablestart;
import android.os.Bundle;
import android.app.Activity;
import android.widget.ListView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_list);
ListView listView = (ListView) findViewById(R.id.mylist);
String[] values = new String[] {"item 1", "item 2", "item 3"};
MyAdapter adapter = new MyAdapter(this, values);
listView.setAdapter(adapter);
}
}
MyAdapter
package cz.skil.android.tut.testtextviewdrawablestart;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class MyAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] values;
public MyAdapter(Context context, String[] values) {
super(context, R.layout.row, values);
this.context = context;
this.values = values;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.row, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.mylabel);
textView.setText(values[position]);
return rowView;
}
}
The main_list.xml layout:
<?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"
android:orientation="vertical" >
<ListView
android:id="#+id/mylist"
android:layout_width="match_parent"
android:layout_height="wrap_content" > <!-- Update: here is the bug -->
</ListView>
</LinearLayout>
and finally the row.xml layout:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mylabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="4dp"
android:drawablePadding="8dp"
android:drawableStart="#drawable/reminder"
android:lines="1"
android:textSize="24sp" >
</TextView>
I guess the reason is that the height of the area for displaying the items is calculated from dimensions declared for the text; however, the icon possibly forces a bigger height for the list item.
Can you confirm the behaviour? If yes, why it behaves so? I am new to Android. It is likely I am doing it wrongly.
(The question is loosely related to this one: Android layout: on TextView and android:drawableStart -- setting size of the icon?).
It's always wrong to set android:layout_height="wrap_content" for a ListView. It works as expected with android:layout_height="fill_parent". More detailed explanation could be found here The World of ListView
Though I don't know if this is intended behaviour or bug, this happens when you use drawableStart. Change it to drawableLeft and it will draw the layout properly.
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mylabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="4dp"
android:drawablePadding="8dp"
android:drawableLeft="#drawable/reminder"
android:lines="1"
android:textSize="24sp" >
</TextView>
I'm pretty new to Android and I have been playing about with GridView. I've got stuck trying to retrieve Strings from individual elements of the GridView so that I can save state based on the changes a user has made.
I've mocked up a stripped down version of what I'm trying to do for this question:
The view of each element in the grid is made up of a TextView and an EditText defined by the following xml file; grid_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id = "#+id/single_item_id"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<TextView
android:id = "#+id/label"
android:layout_width = "fill_parent"
android:layout_height="wrap_content"
android:inputType="text">
</TextView>
<EditText
android:id = "#+id/item_value"
android:layout_width = "fill_parent"
android:layout_height="wrap_content"
android:inputType="text">
</EditText>
</LinearLayout>
My main.xml, consisting of a button and a gridview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="#+id/editbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onRetrieveButtonClick"
android:text="#string/get" android:clickable="true"/>
<GridView
android:id="#+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:columnWidth="250dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:paddingTop="50dp">
</GridView>
</LinearLayout>
My Activity Class:
package com.jdev.simplegrid;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.GridView;
import android.widget.Toast;
public class SimpleGridActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
GridView gridview = (GridView) findViewById(R.id.gridview);
//Some hard-coded sample data -each person has a birth-name and a nickname
ArrayList<Person> people = new ArrayList<Person>();
people.add(new Person("David","Dave"));
people.add(new Person("Bruce","Batman"));
people.add(new Person("John","J"));
gridview.setAdapter(new SimpleAdapter(this, people));
}
public void onRetrieveButtonClick(View view)
{
Toast.makeText(getBaseContext(), "Get the String value of EditText at position 1 of the gridview e.g Batman", Toast.LENGTH_LONG).show();
//Get the String value of EditText at position 1 of the gridview. e.g Batman
}
}
And finally my Adapter for the view:
package com.jdev.simplegrid;
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.TextView;
public class SimpleAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<Person> personList;
public SimpleAdapter(Context c, ArrayList<Person> people) {
mContext = c;
personList = people;
}
public int getCount() {
return personList.size();
}
public Person getItem(int position) {
return personList.get(position);
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view=inflater.inflate(R.layout.grid_item, parent, false);
TextView birthnameLabel=(TextView)view.findViewById(R.id.birthname);
birthnameLabel.setText(personList.get(position).getBirthname());
EditText nicknameText=(EditText)view.findViewById(R.id.nickname);
nicknameText.setText(personList.get(position).getNickname());
return view;
}
}
So my question is, how do I retrieve the a value from the gridview on the click of a button. Say the value "Batman" in EditText at position 1 of the gridview.
I feel like I'm really missing something here!
gridview.getAdapter().getItem(1).getNickname();
Is that what you're looking for? assuming your Person object has a getter method for the nickname of course. - Sorry, obviously I could've seen that in your custom adapter.
If your the idea is the user can change the nickname in the EditText, you'll probably want to add a TextChangedListener (TextWatcher) to each of them and after editting update the nickname on the Person object associated with that position in the grid; e.g. with the help of a setNickname(String) method.
The easiest way to think about this is probably in terms of 'models' and 'views'. The TextViews and EditTexts are the views, whereas the Person objects in the adapter are the models. If you want to make any changes to the data, modify the underlying models with some logic and simply have the views update/refresh after that.
I am trying to create a simple program which displays a "shopping
cart" list of items, along with a few buttons below it to manage the
cart.
The biggest problem is that items are getting duplicate entries in the
list view. That is, for every item I want to enter I see it appear
two times in the list view. What's the problem? Also, the scrollable
area of my cart is not big enough. How do I set it so that it is
bigger but I can still see my buttons? Perhaps I should put the
buttons above the cart?
Here is my shopping cart's layout XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Shopping Cart" />
<ScrollView android:id="#+id/ScrollView01"
android:layout_width="fill_parent"
android:layout_height="110px">
<ListView
android:id="#+id/BookList"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</ListView>
</ScrollView>
<Button android:text="Add Another Book"
android:id="#+id/AddAnother"
android:layout_width="250px"
android:textSize="18px"
android:layout_height="55px">
</Button>
<Button android:text="Checkout"
android:id="#+id/Checkout"
android:layout_width="250px"
android:textSize="18px"
android:layout_height="55px">
</Button>
</LinearLayout>
Here is the layout for individual row items:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="8dip">
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="fill_parent">
<TextView
android:id="#+id/BookTitle"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:singleLine="true"
android:gravity="center_vertical"
/>
<TextView
android:id="#+id/BookPrice"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="marquee"
/>
</LinearLayout>
<Button
android:id="#+id/buttonLine"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:text="Delete"
/>
</LinearLayout>
here is the java code for the shopping cart activity:
package com.sellbackyourbook.sellback;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import android.app.Activity;
//import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
public class cart extends Activity
{
private ListView m_bookListView;
private BookAdapter m_adapter;
//private static String[] data = new String[] = { ""
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState)
{
ShoppingCartSingleton shoppingCart = ShoppingCartSingleton.getInstance();
super.onCreate(savedInstanceState);
setContentView(R.layout.shoppingcart);
this.m_adapter = new BookAdapter(this, R.layout.cartitem,
shoppingCart.m_books);
m_bookListView = (ListView) findViewById(R.id.BookList);
m_bookListView.setAdapter(this.m_adapter);
//setListAdapter(this.m_adapter);
if (shoppingCart.m_books != null && shoppingCart.m_books.size() > 0)
{
//m_adapter.notifyDataSetChanged();
try
{
//m_adapter.clear();
//for(int i=0;i<1;i++)
Log.i("ARRAY", "m_books.size() before loop" + shoppingCart.m_books.size());
int size = shoppingCart.m_books.size();
for(int i=0;i<size;i++)
{
Log.i("ARRAY", "size in loop" + size);
Log.i("ARRAY", "adding item to adapter" + i);
m_adapter.add(shoppingCart.m_books.get(i));
}
} catch (RuntimeException e) {
e.printStackTrace();
}
//m_adapter.notifyDataSetChanged();
}
Button buttonAddAnother = (Button) findViewById(R.id.AddAnother);
buttonAddAnother.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
Intent intent = new Intent();
setResult(RESULT_OK, intent);
finish();
}
});
// TODO: only show this button if the shopping cart is not empty
Button buttonCheckout = (Button) findViewById(R.id.Checkout);
buttonCheckout.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
// TODO: open sellbackyourbook website using book ISBNs
ShoppingCartSingleton shoppingCart = ShoppingCartSingleton.getInstance();
String isbnList = "";
String checkoutURL = "http://www.sellbackyourbook.com/androidcart.php?isbn=";
for (Iterator<Book> i = shoppingCart.m_books.iterator(); i.hasNext(); )
{
Book currentBook = (Book) i.next();
isbnList = isbnList + currentBook.getBookISBN() + ",";
}
checkoutURL = checkoutURL + isbnList;
Log.i("CHECKOUT URL", "checkout URL to submit: " + checkoutURL);
Intent myIntent = new Intent(Intent.ACTION_VIEW);
myIntent.setData(Uri.parse(checkoutURL));
startActivity(myIntent);
}
});
}
private class BookAdapter extends ArrayAdapter<Book> {
private ArrayList<Book> books;
public BookAdapter(Context _context, int _textViewResourceId, ArrayList<Book> _books)
{
super(_context, _textViewResourceId, _books);
this.books = _books;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
System.out.println("getView " + position + " " + convertView);
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.cartitem, null);
}
Book b = books.get(position);
if (b != null)
{
TextView bTitle = (TextView) v.findViewById(R.id.BookTitle);
TextView bPrice = (TextView) v.findViewById(R.id.BookPrice);
if (bTitle != null)
{
bTitle.setText(b.getBookTitle());
}
if (bPrice != null)
{
bPrice.setText(b.getBookPrice());
}
}
return v;
}
}
}
Here is the Java code for my shopping cart. Am I using the singleton correctly? I really just wanted a quick and dirty way to allow multiple activities access to the shopping cart, as a different activity actually grabs the books from the user and this activity displays them in the cart.
I had an issue iterating through the books in onCreate() as well. the size() function kept increasing in the loop for some reason, so I changed the code and added a "size" variable to avoid making the size() call in the loop itself. I'm not really sure what that was all about.
I'm doing exactly the same thing and my getView is not called at all.
here is the script I was inspired by maybe it would help :
http://mfarhan133.wordpress.com/2010/10/14/list-view-tutorial-for-android/
Yes you are right at the point of BookAdapter's constructor. But the getView() method of BookAdapter is wrong. Please have a look at http://www.youtube.com/watch?v=wDBM6wVEO70 (from Google) to get the right way on how to work with ListView.
Removing the loop where I had this fixed the problem:
m_adapter.add(shoppingCart.m_books.get(i));
It seems like the BookAdapter constructor already took care of populating it, so I was duplicating the items by using the add() method.