DB results into a ListView, data may vary - android

Hi a bit new to java/android programming, I am trying to populate a listview from a database. The problem is the database output for each record may have varying results. To give you an idea I have the following layout in my xml for the listview;
<?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"
android:background="#a28d7a">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/coreHeader"
android:textColor="#ffffff"
android:padding="4dp" />
<LinearLayout
android:id="#+id/coreLinear"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Small Text"
android:id="#+id/coreStatsLeft"
android:textColor="#ffffff" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Small Text"
android:id="#+id/textView"
android:textColor="#ffffff"
android:textAlignment="textEnd"
android:gravity="right" />
</LinearLayout>
</LinearLayout>
The first TextView is the header of sorts, bigger font, etc.. in this area it will hold two fields from the database, the NAME and the LEVEL e.g; SPIDER-MAN (Lvl 5).
The two textfields below it will hold the stats, this area can have more than one for example;
Name Value
------------------------------------
Armor 10%
Speed 5%
... and so on
Each record can be different, some may not have speed, some may not have armor... Maybe this is too difficult to do via ListView, but I need it to be searchable and I do not know what other options I have available for this.
My database fields are as follows:
Id, Name, Level, Stats
an example of the populated db would read;
1, Spider-Man, 5, 3|10%;5|5%;6|3%

I created a example to show how to add variable data to each row in a listview.
This is the Activity implementation:
public class MainActivity extends AppCompatActivity
{
private DynamicAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Simulating variable data per row. Array Adapter instead Cursor Adapter for simplicity
final DataRow[] data =
{
new DataRow("Spider Man", new String[] {"3|10%", "5|25%"}),
new DataRow("Spider Man Brother", new String[] {"3|20%"}),
new DataRow("Other Spider Man", new String[] {"3|22%", "1|12%", "4|7%"})
};
// Assign data to adapter
adapter = new DynamicAdapter(this, data);
// Getting reference to ListView
ListView listViewData = (ListView) findViewById(R.id.listViewData);
// Setting adapter to listView
listViewData.setAdapter(adapter);
}
}
This is how the Adapter will put the data for each row:
public class DynamicAdapter extends ArrayAdapter<DataRow>
{
private final Context context;
private final DataRow[] data;
public DynamicAdapter(Context context, DataRow[] data)
{
super(context, R.layout.row_layout, data);
this.context = context;
this.data = data;
}
#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_layout, parent, false);
// Get a listview reference
LinearLayout linearLayoutRow = (LinearLayout) rowView.findViewById(R.id.coreLinear);
if(position < data.length)
{
// Put text on header
TextView textHeader = (TextView) rowView.findViewById(R.id.coreHeader);
// Set the header for this row
textHeader.setText(data[position].GetHeader());
// Creating a vertical linear layout to put the data row
LinearLayout linearLayoutData = new LinearLayout(context);
linearLayoutData.setOrientation(LinearLayout.VERTICAL);
// Get column amount for this row.
int columnAmount = data[position].GetColumnsSize();
for(int i = 0; i < columnAmount; i++)
{
// Creating dynamically a TextView for this column.
TextView dynamicData = new TextView(context);
dynamicData.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
// Adding data to TextView
dynamicData.setText(data[position].GetDataAt(i));
// Adding TextView to linearLayout
linearLayoutData.addView(dynamicData);
}
// Adding LinearLayout to LinearLayout on XML
linearLayoutRow.addView(linearLayoutData);
}
return rowView;
}
}
This is the full demo on Github: https://github.com/deinier/DynamicDataOnListView
I hope this help.

Related

Setting TextView visible(or gone) in ListView

I am tying to set a textview inside my ListView visible depending on another variable. But when I try
TextView sdate;
TextView stime;
sdate= (TextView) findViewById(R.id.date);
stime= (TextView) findViewById(R.id.time);
It seems like it can't find the 2 in the layout?
From what I gather, there needs to be something in front of the findViewbyId() but I'm not sure on what. The items layout in the list is done by list_item.xml. The code that is handling all this is:
ListAdapter adapter;
if(add.equals("Event")){
stime.setVisibility(View.VISIBLE);
sdate.setVisibility(View.VISIBLE);
adapter = new SimpleAdapter(
AllSpotsActivity.this, spotsList,
R.layout.list_item, new String[] { TAG_PID,
TAG_NAME, "sdistance","dateof","timeof" }, new int[] {
R.id.pid, R.id.name, R.id.distance, R.id.date, R.id.time});
}else{
adapter = new SimpleAdapter(
AllSpotsActivity.this, spotsList,
R.layout.list_item, new String[] { TAG_PID,
TAG_NAME, "sdistance" }, new int[] {
R.id.pid, R.id.name, R.id.distance });
}
Thank you in advance,
Tyler
EDIT:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/gradient_background"
>
<!-- Product id (pid) - will be HIDDEN - used to pass to other activity -->
<TextView
android:id="#+id/pid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
<!-- Name Label -->
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="6dip"
android:paddingLeft="6dip"
android:textSize="17dip"
android:textStyle="bold" />
<!-- Name Label -->
<TextView
android:id="#+id/distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:paddingRight="6dip"/>
<TextView
android:id="#+id/date"
android:layout_below="#id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="12dip"
android:visibility="gone"/>
<TextView
android:id="#+id/time"
android:layout_below="#id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:paddingRight="6dip"
android:visibility="gone"/>
</RelativeLayout>
EDIT 2:
I've also tried using lv.findViewById() because lv=getListView(); But that did not work either.
I think you should call findViewById() on each row's view. For example, if you are calling that method from the getView() method of your adapter, you should use convertView.findViewById.
If you want to have anything more than a simple TextView as the layout for each item in a ListView, what you'll need to do is create a custom adapter that extends ArrayAdapter. Inside of the getView() method of your custom adapter, you will have access to your custom xml layout (one of the arguments to the constructor of the ArrayAdapter is the resource ID of the layout file you want to have for each item in the list [e.g., R.layout.your_custom_list_item]). From inside of that method, you will have access to either a new or recycled view, which you can inflate your custom layout within.
The LayoutInflater.inflate() method you call from inside the getView() method will return you a view that you can call findViewById() on to get access to all the views in your custom layout that you want to interact with. It's there that you can make your views visible or invisible based on the data you pass into the adapter (the third argument to the adapter's constructor is either a list or an adapter with the data you want to use to populate the views). I strongly recommend you watch the I/O video on ListViews for a more complete explanation. I've also included some sample code for a custom adapter below.
public class BookingSearchResultsAdapter extends ArrayAdapter<SearchResult> {
private static final String TAG = BookingSearchResultsAdapter.class.getName();
private int mLayoutResourceId;
private Context mContext;
private List<SearchResult> mResults = null;
public BookingSearchResultsAdapter(Context context, int resource, List<SearchResult> results) {
super(context, resource, results);
mContext = context;
mLayoutResourceId = resource;
mResults = results;
}
/**
* #return A view to display search result
*/
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
SearchResultVendorViewHolder holder = null;
// if there is no recycled view available
if(row == null) {
Log.d(TAG, "No recyclable custom view found. New view created.");
// get a new search result view
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
row = inflater.inflate(mLayoutResourceId, parent, false);
// store all static view information in a holder
holder = new SearchResultVendorViewHolder();
holder.imgIcon = (ImageView) row.findViewById(R.id.search_result_establishment_icon);
holder.txtTitle = (TextView) row.findViewById(R.id.search_result_establishment_name);
holder.txtDescription = (TextView) row.findViewById(R.id.search_result_establishment_description);
// attach the holder to the view so that it can be recycled
row.setTag(holder);
}
else {
Log.d(TAG, "View recycled");
// get the recycled view (stored in tag)
holder = (SearchResultVendorViewHolder)row.getTag();
}
// initialize data in custom search result view
SearchResult result = (SearchResult) mResults.get(position);
holder.txtTitle.setText(result.getEstablishmentName());
holder.imgIcon.setImageResource(result.getImageId());
holder.txtDescription.setText(result.getDescription());
Log.d(TAG, "Custom search view data initialized");
return row;
}
static class SearchResultVendorViewHolder {
ImageView imgIcon;
TextView txtTitle;
TextView txtDescription;
}
}

Android: button showing up multiple times in list view

I trying to write code to highlight the selected value of the list with "Next" button at the bottom of the layout. But for some reason, after every list item, "next" button also shows up. Can someone please help me resolve this problem?
Here is the layout file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/questionLayout"
>
<TextView android:id="#+id/txtExample"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="25sp"
android:textColor="#000000"
android:background="#FF0000"
/>
<ListView
android:id="#+id/listExample"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#CCCCCC"
android:choiceMode="singleChoice"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<Button
android:id = "#+id/next"
android:text="Next"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_gravity="center"
android:layout_weight="50"
/>
<Button
android:id = "#+id/submit"
android:text="Submit"
android:layout_width = "0dp"
android:layout_height = "wrap_content"
android:layout_weight="50"
android:layout_gravity="center"
/>
</LinearLayout>
</LinearLayout>
Java Code:
public class updateList extends Activity {
private SelectedAdapter selectedAdapter;
private ArrayList<String> list;
int correct_answer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = new ArrayList<String>();
list.add("Choice One");
list.add("Choice Two");
list.add("Choice Three");
selectedAdapter = new SelectedAdapter(this,0,list);
selectedAdapter.setNotifyOnChange(true);
ListView listview = (ListView) findViewById(R.id.listExample);
listview.setAdapter(selectedAdapter);
listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View view,
int position, long id) {
// user clicked a list item, make it "selected"
selectedAdapter.setSelectedPosition(position);
}
});
}
}
Thanks in advance
SSP
Selected Adaptor class:
public class SelectedAdapter extends ArrayAdapter{
// used to keep selected position in ListView
private int selectedPos = -1; // init value for not-selected
public SelectedAdapter(Context context, int textViewResourceId,
List objects) {
super(context, textViewResourceId, objects);
}
public void setSelectedPosition(int pos){
selectedPos = pos;
// inform the view of this change
notifyDataSetChanged();
}
public int getSelectedPosition(){
return selectedPos;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
// only inflate the view if it's null
if (v == null) {
LayoutInflater vi = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.activity_main, null);
}
// get text view
TextView label = (TextView)v.findViewById(R.id.txtExample);
// change the row color based on selected state
if(selectedPos == position){
label.setBackgroundColor(Color.CYAN);
}else{
label.setBackgroundColor(Color.WHITE);
}
label.setText(this.getItem(position).toString());
/*
// to use something other than .toString()
MyClass myobj = (MyClass)this.getItem(position);
label.setText(myobj.myReturnsString());
*/
return(v);
}
}
change your listview in xml as like this
<ListView
android:id="#+id/listExample"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"//===== set maximum heighthere
android:layout_marginBottom="50dp"// === give some space at bottom so that buttons will appear
android:background="#CCCCCC"
android:choiceMode="singleChoice"
/>
But for some reason, after every list item, "next" button also shows up.
The ListView's row layout is determined by the layout you inflate in getView() or pass to your Adapter's super class if you haven't overridden getView(). Double check this layout and remove the unwanted code.
Addition
The layout for your ListView's items only needs to be one TextView since you only want to display a phrase in each. However you are currently passing your entire main layout, this creates the Buttons, an unused ListView, and everthing else in every row...
Instead use android.R.layout.simple_list_item_1 in getView(), of course you'll need to change the id you pass to findViewById() as well:
if (v == null) {
LayoutInflater vi = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(android.R.layout.simple_list_item_1, null);
}
// get text view
TextView label = (TextView)v.findViewById(android.R.id.text1);
Please watch Android's Romain Guy discuss writing an efficient adapter to speed things up.

Why is my custom SimpleCursorAdapter returning different reults when ListView is scrolling

I'm trying to implement a custom SimpleCursorAdapter in order to switch out layouts in a ListView but I'm getting very random results while scrolling.
My issue here is that when I scroll up and down, the ListView seemingly by random, mix up the layouts. For instance, a row can have the listview_item_row layout at first but when scrolling in and out of the screen it can be replaced by listview_item_reply_row and back again.
I can't say I've really understood how newView works. I have successfully been able to use bindView to determine if I'm to hide an image in the layout or not but new View is veiled in darkness to me about its implementation and why the list scrolling behaves the way it does.
My goal is to have a list with x amount of items. Depending on if the item is a reply or a new message I want to load a specific layout on that row. Depending on if the row has an image or not I want to show/hide the imageview in the row layout.
What I have omitted in the code are the imports and row layouts. I'm trying to implement this by using Fragments and SimpleCursorAdapter in the v4 support package. The row layouts for the ListFragment are visibly different but contain the same widgets.
The ListView layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/text_feed_header_random"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:padding="4dp"
android:text="Allmänt"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#FFF" />
<!--
The frame layout is here since we will be showing either
the empty view or the list view.
-->
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#id/text_feed_header_random"
android:layout_above="#+id/footer" >
<!--
Here is the list. Since we are using a ListActivity, we
have to call it "#android:id/list" so ListActivity will
find it
-->
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:drawSelectorOnTop="false" />
<!-- Here is the view to show if the list is emtpy -->
<TextView
android:id="#android:id/empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="No items."
android:textAppearance="?android:attr/textAppearanceMedium" />
</FrameLayout>
<LinearLayout
android:id="#+id/footer"
style="#android:style/ButtonBar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal" >
<Button
android:id="#+id/button_random_post"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Gör ett inlägg!" />
<Button
android:id="#+id/button_random_refresh"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Refresh list!" />
</LinearLayout>
</RelativeLayout>
A condensed Fragment using the layout above:
public class RandomFragment extends ListFragment implements LOG {
private DatabaseHelper mDbHelper;
private KarenfeedCursorAdapter mAdapter;
private Cursor mCursor;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "RANDOMFRAGMENT START!");
mDbHelper = new DatabaseHelper(getActivity());
mDbHelper.open();
mDbHelper.setTable(Posts.TABLE_RANDOM_POSTS);
//TODO: Replace SimpleCursorAdapter with a FragmentList instead...
mCursor = mDbHelper.getAllPostsSortedCursor();
String[] columns = { Posts.COLUMN_ID, Posts.COLUMN_CREATED, Posts.COLUMN_USER, Posts.COLUMN_COMMENT };
int[] to = { R.id.imageItemPhoto, R.id.textItemDate, R.id.textItemUser, R.id.textItemComment };
int flags = 0;
mAdapter = new FeedCursorAdapter(getActivity(), R.layout.listview_item_row, mCursor, columns, to, flags);
this.setListAdapter(mAdapter);
initFeedList(); // This call in the end executes mCursor = mDbHelper.getAllPostsSorted(); mAdapter.changeCursor(mCursor); mAdapter.notifyDataSetChanged();
}
}
The SimpleCursorAdapter that the ListFragment connects to:
public class FeedCursorAdapter extends SimpleCursorAdapter implements LOG {
private Context mContext;
private int mLayout;
public FeedCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
super(context, layout, c, from, to, flags);
// TODO Auto-generated constructor stub
mContext = context;
mLayout = layout;
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
View view;
int id = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_ID));
int parentId = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_PARENT_ID));
Log.d(TAG, "id: " +id+ " parentId: " +parentId);
int hasImage = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_IMAGE));
if(id == parentId) {
view = inflater.inflate(R.layout.listview_item_row, parent, false);
} else {
view = inflater.inflate(R.layout.listview_item_reply_row, parent, false);
}
return view;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
Log.d(TAG, "bindView()");
int id = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_ID));
int parentId = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_PARENT_ID));
int hasImage = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_IMAGE));
String date = cursor.getString(cursor.getColumnIndex(Posts.COLUMN_CREATED));
String user = cursor.getString(cursor.getColumnIndex(Posts.COLUMN_USER));
String comment = cursor.getString(cursor.getColumnIndex(Posts.COLUMN_COMMENT));
TextView dateView = (TextView) view.findViewById(R.id.textItemDate);
TextView userView = (TextView) view.findViewById(R.id.textItemUser);
TextView commentView = (TextView) view.findViewById(R.id.textItemComment);
ImageView imageView = (ImageView) view.findViewById(R.id.imageItemPhoto);
dateView.setText(date);
userView.setText(user);
commentView.setText(comment);
if(hasImage == 0) {
imageView.setVisibility(ImageView.GONE);
} else {
String bitmapPath = Environment.getExternalStorageDirectory().getPath() + "/feed/" + id + "_thumb.jpg";
Bitmap bitmap = BitmapFactory.decodeFile(bitmapPath);
BitmapDrawable bitmapDrawable = new BitmapDrawable(bitmap);
imageView.setImageDrawable(bitmapDrawable);
imageView.setVisibility(ImageView.VISIBLE);
}
}
}
after reading your question and the code i think you should know that whenever you scroll a listview up or down it communicates with the adapter to populate the new items that came in to focus and for the case of different row for different data you should make a arraylist that will contain the name or id of the items whose backgrounds are different and then you start making there background according to your need on every call to adapter.

Button press add new row to a ListView programmatically, how to?

My main layout main.xml has only a Button, a EditText and an empty ListView as below:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
>
<LinearLayout
android:id="#+id/input_area"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<EditText
android:id="#+id/input_field"
android:layout_height="40dip"
android:layout_width="fill_parent"
android:layout_weight="5"
/>
<Button
android:id="#+id/send_btn"
android:layout_width="60dip"
android:layout_height="30dip"
android:text="#string/send"
android:layout_weight="1"
/>
</LinearLayout>
<LinearLayout
android:id="#+id/output_area"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#006633"
android:visibility="gone"
>
<ListView
android:id="#+id/output_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="10dip"
>
<!-- When "send" button in above input_area is pressed,
text from EditText field show here programmatically as a new row of the listview-->
</ListView>
</LinearLayout>
</LinearLayout>
As you see above, there are two child LinearLayout hosted by main LinearLayout.
The 1st child LinearLayout with id input_area consists of a EditText and a Button.
The 2nd child LinearLayout with id output_area is an LinearLayout with an empty ListView, AND its visibility is set to "gone".
The feature I am going to implement is very simple, that's in the input_area, when user input some text in the EditText field, and press the send button, then the input string should be shown in the output LinearLayout as a new row of the listview programmatically.
What I tried is the java code below:
EditText inputTxt = (EditText) findViewById(R.id.input_field);
Button sendBtn = (Button) findViewById(R.id.send_btn);
LinearLayout outputArea = findViewById(R.id.output_area);
//Updated by Saurabh
ListView lv = findViewById(R.id.output_list);
MyListAdapter mAdapter = new MyListAdapter(this, arraylist);
//Update finished
sendBtn.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
int visibility = outputArea.getVisibility();
if(visibility==View.GONE)
// set ListView visible
outputArea.setVisibility(View.VISIBLE);
//get user input
String userInput = inputTxt.getText().toString(); // show this string in a new row of listview
//BUT how to dynamically add new row to the listview here???
}
});
But I am not sure how to add new row to the listview programmatically, anyone can help me?
By the way, I have another layout xml fiel (row.xml) which defined each row's layout.
-----------------------UPDATE------------------------------------
Each row of the list contain a icon and a text string. My list adapter and row layout are showing below:
My adapter:
private static class MyListAdapter extends BaseAdapter {
private LayoutInflater mInflater;
ArrayList<String> arraylist;
public MyListAdapter(Context context, ArrayList<String> arraylist) {
mInflater = LayoutInflater.from(context);
this.arraylist = arraylist;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.row, null);
holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
holder.userInput = (TextView) convertView.findViewById(R.id.user_input);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.icon.setImage(???);
holder.userInput.setText(arraylist.get(position));
return convertView;
}
static class ViewHolder {
ImageView icon;
TextView userInput;
}
}
my list row layout:
<?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="horizontal"
>
<ImageView
android: id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="#+id/user_input"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textSize="10dip"/>
</LinearLayout>
Make a Global variable as below
ArrayList<String> arraylist = new ArrayList<String>();
On Click of send button update the adapter that you are setting on ListView by adding
String userInput = inputTxt.getText().toString();
arraylist.add(userInput)
in adapter and then call
adapter.notifyDataSetChanged();
Update
I updated answer in your question and in this post copy your new Adapter class and use that

build layout at runtime android

i have a complex xml layout which has list views..a row in the list view contains several text fields which are spaced evenly. i am using textview to store the text and then finally add all the items to the row...its working perfectly fine.
but now i have case where in i am not sure, how many text fields i might get from a webservice. therefore i need to create the textview dynamically on run time, populate them and then insert into the list..
is there anyway to declare,add and populate new textview fields on runtime?
or is there is anyway to implement the spacing between the two fields?
result of first call
__________________________
|_____|_____|_____|______|
result of second call
________________________________
|_____|_____|_____|______|______|
I tried implementing the solution that was provided below (Kenny), but for some reason I am unable to add views into the list.. below is my code
public class HeaderAdapter extends ArrayAdapter<Header> {
final Header[] listSymbols;
private TextView textView;
private LinearLayout row;
public HeaderAdapter(Context context, int symResourceID,
Header[] objects) {
super(context, symResourceID, objects);
listSymbols = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.header_view, parent, false);
Header headerRec = listSymbols[position];
for(int i = 0 ; i < listSymbols.length;i++){
textView = new TextView(getContext());
textView.setLayoutParams(new LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, //Width of the view
ViewGroup.LayoutParams.WRAP_CONTENT));//Height of the view
textView.setId(i);
row.add??
}
}
The main activity that calls this
setContentView(R.layout.main);
headerList.add(new Header("Symbol","Quantity","Price","Price Yesterday","52 Week High","52 Week Low","Change","Days Gain","Days Gain %","Returns"));
Header[] tmpHeaderList = headerList.toArray(new Header[headerList.size()]);
ArrayAdapter<Header> headerAdapter = new HeaderAdapter(this,R.layout.twoway_header_view,tmpHeaderList);
headerListView.setAdapter(headerAdapter);
xml layout file..the main file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<HorizontalScrollView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:scrollbars="none"
android:id="#+id/headerHv">
<ListView android:id="#+id/header_listView1"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:background="#color/white" android:cacheColorHint="#00000000"
android:smoothScrollbar="true" android:scrollbars="none" />
</HorizontalScrollView>
</LinearLayout>
the file in which the template for the row is defined
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView android:id="#+id/headerList" android:layout_width="80dp"
android:layout_height="wrap_content" android:textColor="#000000"
android:typeface="sans" android:textStyle="normal" />
</LinearLayout>
Here is the way i dynamically generate custom buttons from a list, you could do the same thing with textViews:
//Setup Buttons
layout = (LinearLayout)findViewById(R.id.layoutBars);
int count = lBars.size();
for(int i = 0; i< count;i++){
final Bar b = lBars.get(i);
BarButton button = new BarButton(DDTBars.this, R.drawable.barsmall , b.getName().toUpperCase());
button.setLayoutParams(new LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
button.setId(i);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//Run activity passing name of the bar to retrieve data
Intent i = new Intent(DDTBars.this, DDTBar.class);
i.putExtra("name", b.getName());
startActivity(i);
}
});
layout.addView(button);
}
So you could try:
//Setup TextViews
layout = (LinearLayout)findViewById(R.id.mylayout);
int count = myTextList.size();
for(int i = 0; i< count;i++){
TextView txtView = new TextView(this);
txtView.setLayoutParams(new LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, //Width of the view
ViewGroup.LayoutParams.WRAP_CONTENT));//Height of the view
txtView.setId(i);
layout.addView(txtView);
}
You could do it in code. Declare TextView 's in a loop and use RelativeLayout to position them wrt each other.

Categories

Resources