I am making an application which displays weather information. To display the weather, i am using the nadavfima google cards ui library. But, when i try to set the textviews in my layout for the card, it does not display even after refreshing in the app. All it displays is the hardcoded values i set in the xml file.
mCards = (CardUI) root.findViewById(R.id.nowCards);
mCards.setSwipeable(false);
// add cards
// add overview card
mCards.addCard(new NowOverviewCard());
mCards.addStack(new CardStack());
// add temperature
mCards.addCard(new SimpleTempCard(getActivity()));
mCards.addStack(new CardStack());
// add detailed values
SimpleValueCard pressure = new SimpleValueCard(getActivity());
mCards.addCard(pressure);
mCards.refresh();
layout view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="15dp" >
<TextView
android:id="#+id/simpleCardHead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:fontFamily="sans-serif-thin"
android:text="Humidity"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/simpleCardValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/simpleCardHead"
android:layout_alignBottom="#+id/simpleCardHead"
android:layout_marginLeft="35dp"
android:layout_toRightOf="#+id/simpleCardHead"
android:fontFamily="sans-serif-thin"
android:text="75%"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
My Card view
public class SimpleValueCard extends Card {
View card;
private Context ctx;
public SimpleValueCard( Context ctx) {
this.ctx = ctx;
}
#Override
public View getCardContent(Context context) {
return getViewFromContext(context);
}
#Override
public boolean convert(View convertCardView) {
getViewFromContext(ctx);
TextView header = (TextView) convertCardView
.findViewById(R.id.simpleCardHead);
TextView value = (TextView) convertCardView
.findViewById(R.id.simpleCardValue);
if (header == null || value == null) {
} else {
header.setText("Pressure");
value.setText("84");
}
return true;
}
private View getViewFromContext(Context context) {
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
card = mInflater.inflate(R.layout.card_simple_value, null);
return card;
}
}
The problem is you are calling getViewFromContext(ctx); which return view object but unfortunately you are not using/saving that view object in your convert(View convertCardView).
So you need to store that returned view object & then you should use it in your convert(View convertCardView). It is just like custom listview baseadapter. You need that view object with the help of it you can set your textviews. Because here you are inflating but not exactly using that view object thatswhy its showing static values.
Do above thing, it will surely solve your problem.
Refer Android Custom ListView + BaseAdapter
Related
I recently started to use ListView on Android Application and I'm not making it to display at the screen.
I saw many tutorials on how to do a custom Adapter and followed it line by line, but at the end I wasn't able to make the ListView display on my screen, I even let a fixed Text in one TextView to display at the ListView but it still didn't displayed it.
This is the constructor of my entity code:
public Classificacao(int colocacao, int time, int pontos) {
this.colocacao = colocacao;
this.time = time;
this.pontos = pontos;
}
This my Custom Adapter that extends "ArrayAdapter"
private Context context;
private ArrayList<Classificacao> classificacaoList;
ClassificacaoAdapter(Context context, ArrayList<Classificacao> classificacaoList) {
super(context, R.layout.layout_classificacao, classificacaoList);
this.context = context;
this.classificacaoList = classificacaoList;
}
#SuppressLint("SetTextI18n")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(convertView == null){
convertView = layoutInflater.inflate(R.layout.layout_classificacao, parent, false);
}
TextView colocacao = convertView.findViewById(R.id.texto1);
colocacao.setText(Integer.toString(classificacaoList.get(position).getColocacao()));
ImageView imagem = convertView.findViewById(R.id.imagem1);
imagem.setImageResource(classificacaoList.get(position).getImagem());
TextView nome = convertView.findViewById(R.id.texto2);
nome.setText(classificacaoList.get(position).getTime());
TextView pontos = convertView.findViewById(R.id.texto3);
pontos.setText(Integer.toString(classificacaoList.get(position).getPontos()));
return convertView;
}
This the layout "activity_atividade02" that have the ListView, and some others Text views that I won't display here.
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
This is the layout "layout_classificacao" that will be filled by the adapter
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="20dp">
<TextView
android:id="#+id/texto1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:textColor="#android:color/black"
android:textSize="30sp" />
<ImageView
android:id="#+id/imagem1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:layout_weight="1"
android:contentDescription="imagem do time"
app:srcCompat="#drawable/flamengo" />
<TextView
android:id="#+id/texto2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:textColor="#color/colorPrimary"
android:textSize="30sp" />
<TextView
android:id="#+id/texto3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:textColor="#android:color/black"
android:textSize="30sp" />
</LinearLayout>
And this is the main class "Atividade02"
that start everything
public class Atividade02 extends AppCompatActivity {
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_atividade02);
listView = findViewById(R.id.listView);
ArrayList<Classificacao> classificacaoArrayList = new ArrayList<>();
classificacaoArrayList.add(new Classificacao(1, 2,46));
classificacaoArrayList.add(new Classificacao(2, 1,42));
classificacaoArrayList.add(new Classificacao(3,0,38));
classificacaoArrayList.add(new Classificacao(4,3,35));
classificacaoArrayList.add(new Classificacao(5,5,33));
classificacaoArrayList.add(new Classificacao(6,4,33));
ArrayAdapter classificacaoAdapter = new ClassificacaoAdapter(this, classificacaoArrayList);
listView.setAdapter(classificacaoAdapter);
}
}
Resuming, the ListView isn't displaying the "ClassificacaoAdapter" and I want it to do it.
Make sure adapter has the method getItemcount() and it returns the classificacaoList.size(). It should not return 0;
Well... it was a pretty obvious problem, in the main layout activity_atividade02 there was a LinearLayout above the ListView that it's layout_height was set to match_parent and it was occupying the entire layout and not letting the ListView being displayed.
I test your code as you write and found an error here and it works normally but I comment imageView line because you don't define it in Classificacao class
an error here
TextView nome = convertView.findViewById(R.id.texto2);
nome.setText(classificacaoList.get(position).getTime());
setText() accept String only ..but you pass integer rather than String you can do that
nome.setText(""+classificacaoList.get(position).getTimee());
or use
Integer.toString( classificacaoList.get(position).getTimee() )
as you use in other lines
please add getCount() method in your ClassificacaoAdapter class, it is an override method. It will return the size of the list,if you will not override this it will return 0 as your list size.
public int getCount() {
return classificacaoList .size();
}
I have 4 fields on a custom row layout for a listview. I have 4 fields in my array that I want to map to those 4 fields on the listview:
cat_ID_PK
cat_name
cat_amount
is_recurring
I have no idea how to correctly do that. Here's what I have so far:
private void loadListView(Expenses[] mExpenseArray) {
//This code will write the "name" variable correctly to the logcat, so I know I'm
getting the right values in my array.
String name = mExpenseArray[0].getCatName();
Log.v("log_tag", name);
ArrayAdapter<Expenses> adapter = new ArrayAdapter<Expenses>(getApplicationContext(), R.layout.list_row, R.id.catName, mExpenseArray);
final ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(adapter);
}
This code only populates R.id.catName, but when it populates it, it looks like this: mypackage#8ed455 (or something similar). None of the other fields are populated at all, which I'm guessing has to do with the 3rd parameter in my ArrayAdapter being R.id.catName. However, if I take this parameter out I get this error:
java.lang.IllegalStateException: ArrayAdapter requires the resource ID to be a TextView
Here is the code for my custom row layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/list_selector"
android:orientation="horizontal"
android:padding="5dip" >
<TextView
android:id="#+id/catName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dip"
android:layout_centerVertical="true"
android:paddingBottom ="10dip"
android:text="#string/catName"
android:textColor="#040404"
android:textSize="25dip"
android:textStyle="bold"
android:typeface="sans" />
<TextView
android:id="#+id/catAmount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="27dip"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:paddingBottom ="10dip"
android:text="$45.00"
android:textColor="#040404"
android:textSize="25dip"
android:textStyle="bold"
android:typeface="sans" />
<TextView
android:id="#+id/catType"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/catName"
android:layout_alignLeft="#+id/catName"
android:paddingTop="5dip"
android:layout_centerHorizontal="true"
android:text="#string/catType"
android:textColor="#343434"
android:textSize="15dip" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="catID"
android:id="#+id/catID"
android:layout_alignBottom="#+id/catType"
android:layout_toRightOf="#+id/catType"
android:layout_toEndOf="#+id/catType"
android:layout_marginLeft="27dp"
android:visibility="invisible" />
</RelativeLayout>
How can I correctly map my 4 array fields to my ListView?
make a custom adapter like this and then assign the values to the text views
pass array like this to adapter
UserList disadpt = new UserList(HomePage.this, mEmployeeList);
userList.setAdapter(disadpt);
then in adapter do this ..
public class UserList extends BaseAdapter
{
private Context mContext;
private ArrayList<Employee> items;
public UserList(Context c, ArrayList<Employee> items)
{
this.mContext = c;
this.items = items;
}
public int getCount() {
return this.items.size();
}
public Object getItem(int position) {
return this.items.get(position);
}
public long getItemId(int position) {
return position;
}
#Override
public View getView(int pos, View child, ViewGroup arg2) {
Holder mHolder;
LayoutInflater layoutInflater;
if (child == null) {
layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
child = layoutInflater.inflate(R.layout.listcell, null);
mHolder = new Holder();
//mHolder.txt_id = (TextView) child.findViewById(R.id.txt_id);
mHolder.txt_fName = (TextView) child.findViewById(R.id.txt_fName);
mHolder.txt_lName = (TextView) child.findViewById(R.id.txt_lName);
mHolder.txt_userName = (TextView) child.findViewById(R.id.txt_userName);
child.setTag(mHolder);
} else {
mHolder = (Holder) child.getTag();
}
Employee employee = this.items.get(pos);
ArrayList<String> employeeInfo = new ArrayList<String>();
employeeInfo.add(employee.employeeId);
employeeInfo.add(employee.firstName);
employeeInfo.add(employee.lastName);
mHolder.Details.setTag(employeeInfo);
mHolder.txt_fName.setText(employee.firstName + " " + employee.lastName);
mHolder.txt_userName.setText(employee.emailId);
return child;
}
public class Holder
{
//TextView txt_id;
TextView txt_fName;
TextView txt_lName;
TextView txt_userName;
Button Details;
}
}
hope this helps ...
Create String type of array Adapter and use-
adapter.add(mExpenseArray[0].getCatName());
by using any loop.
I have a custom BaseAdapter used for a ListView. The usual layout of a row looks like on the first picture.
Gallery is here
But the list can also have items whose second line's string is empty, like on the second picture, and if that second line's string has a length equal to 0, the second line's view's setVisibility(View.GONE) method is called.
And when the list is filled with items so it's neccessary to scroll to see the most-bottom items, and you scroll down and there is an item with only one line, and you scroll back to top, some of the two-line items can lose their second line, like on the third picture.
A simillar thing happens when an item is deleted from the list - the item going on its place gets the height of the deleted one - like on the fourth picture (forget the colored bar).
So it seems that the adapter thinks the "Cookies" item is the same as the "Something" item... or something.
Why does it happen? How can i fix that?
Another gallery to show exactly what happens
Adapter code:
public class CounterItemAdapter extends BaseAdapter{
private Activity activity;
private ArrayList<CounterItem> data;
private SQLiteOpenHelper helper;
private static LayoutInflater inflater = null;
public CounterItemAdapter(Activity activity, ArrayList<CounterItem> data, SQLiteOpenHelper helper) {
this.activity = activity;
this.data = data;
this.helper = helper;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return data.size();
}
#Override
public CounterItem getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return getItem(position).getId();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if(convertView == null)
view = inflater.inflate(R.layout.counter_list_item, null);
TextView nameView = (TextView)view.findViewById(R.id.nameView);
TextView descView = (TextView)view.findViewById(R.id.descView);
final TextView countView = (TextView)view.findViewById(R.id.countView);
ImageButton plusButton = (ImageButton)view.findViewById(R.id.plusButton);
final CounterItem counterItem;
counterItem = data.get(position);
nameView.setText(counterItem.getName());
if(counterItem.getDesc().length() == 0){
descView.setVisibility(View.GONE);
Log.d(HomeActivity.DEBUG_TAG, "GONE " + counterItem.getName() + ", LENGTH " + counterItem.getDesc().length());
}else
descView.setText(counterItem.getDesc());
countView.setText(counterItem.getCount() + "");
plusButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
counterItem.increment(helper.getWritableDatabase());
countView.setText(counterItem.getCount() + "");
}
});
View categoryView = view.findViewById(R.id.category);
String colors[] = {"#ff99cc00",
"#ff00ddff",
"#ffffbb33",
"#ffaa66cc",
"#ffcc0000"};
Random rand = new Random();
String color = colors[rand.nextInt(colors.length)];
categoryView.setBackgroundColor(Color.parseColor(color));
return view;
}
}
Row layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="false"
android:descendantFocusability="blocksDescendants"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#+id/linearLayout" android:layout_centerVertical="true"
android:gravity="center_vertical" android:paddingLeft="12dp" android:paddingRight="12dp"
android:paddingBottom="8dp" android:paddingTop="8dp" android:id="#+id/linearLayout1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Counter name"
android:id="#+id/nameView"
android:textSize="16dp"/>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
android:id="#+id/descView"
android:textSize="16dp"
android:textColor="#color/dividerGrey"
android:text="wtf"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:id="#+id/linearLayout" android:gravity="center_vertical" android:layout_centerVertical="true"
android:paddingTop="8dp" android:paddingBottom="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="13"
android:id="#+id/countView"
android:textSize="30dp"
android:layout_marginRight="13dp" android:textColor="#color/dividerGrey"/>
<View android:layout_width="0.5dp" android:layout_height="48dp"
android:background="#color/dividerGrey" android:id="#+id/plusDivider"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/plusButton"
android:src="#drawable/ic_button_increment"
style="#android:style/Widget.Holo.Light.ActionButton"
android:contentDescription="#string/plus_button"/>
</LinearLayout>
</RelativeLayout>
Well i suppose you use the ViewHolder pattern in a ListView right?
I don't want to try and explain the whole usage of this pattern as there are many other good tutorials.
So the case you describe happens, because the listAdapter reuses the convertView that was inflated for every object so if the last object for your listview has setVisibility(View.Gone) for your second line then when you scroll up all the other childs that become visible will also have visibility(View.Gone).
A simple workaround for this is to setVisibility for each row
like this:
if (convertView == null) {
convertView = (View) inflater.inflate(R.layout.view_item, null);
viewHolder = new ViewHolder();
viewHolder.itemName = (TextView) convertView.findViewById(R.id.item_name);
viewHolder.secondLine = (TextView) convertView.findViewById(R.id.second_line)
convertView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder) convertView.getTag();
}
if(<-- your condition here-->){
secondLine.setVisibility(View.VISIBLE);
}
else{
secondLine.setVisibility(View.GONE);
}
And now that you have added the code for your adapter i believe that your mistake is here:
if(counterItem.getDesc().length() == 0){
descView.setVisibility(View.GONE);
Log.d(HomeActivity.DEBUG_TAG, "GONE " + counterItem.getName() + ", LENGTH " + counterItem.getDesc().length());
}else {
**descView.setVisibility(View.VISIBLE);**
descView.setText(counterItem.getDesc());
}
You should add code to set it visible again if needed bacause with your code when it gets gone for one of the rows it stays gone forever.
Update
Also for your second problem, whenever you delete an item from your listview you should remove the item from the adapter and call notifyDataSetChanged(); in order for the adapter to recreate the Views.
I have a problem with adding a listview as a header in my listview (go go redundancy). The code is working, however only the first item shows up in the header. The body looks fine.
listView = (ListView) findViewById(R.id.default_list_view);
header = (ListView) getLayoutInflater().inflate(R.layout.savings_overview_header_list, null, false);
HeaderAdapter hAdapter = new HeaderAdapter(getLayoutInflater());
hAdapter.addItem("1");
hAdapter.addItem("2");
hAdapter.addItem("3");
header.setAdapter(hAdapter);
for (Policy p : saving.getPolicies()) {
adapter.addItem(p);
}
listView.addHeaderView(header);
listView.setAdapter(adapter);
headerView:
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/default_list_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="#00000000"
android:divider="#drawable/list_divider"
android:dividerHeight="2px"
android:fadingEdge="none"
android:fitsSystemWindows="true"
android:footerDividersEnabled="false"
android:headerDividersEnabled="false"
android:listSelector="#drawable/list_item_background_selected"
>
</ListView>
I have tried wrapping the ListView in a vertical LinearLayout but no cigar there either :(
hAdapter
private static class HeaderAdapter extends BaseAdapter {
private final LayoutInflater inflater;
protected ArrayList<String> data = new ArrayList<String>();
public HeaderAdapter(LayoutInflater inflater) {
this.inflater = inflater;
}
public void addItem(String s) {
data.add(s);
}
public View getView(int position, View convertView, ViewGroup parent) {
final PolicyViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.savings_overview_header_item, parent, false);
holder = new PolicyViewHolder();
holder.header = (TextView) convertView.findViewById(R.id.list_item_header);
holder.subHeader = (TextView) convertView.findViewById(R.id.list_item_subheader);
holder.img = (ImageView) convertView.findViewById(R.id.list_item_img);
convertView.setTag(holder);
} else {
holder = (PolicyViewHolder) convertView.getTag();
}
String s = data.get(position);
holder.header.setText(s);
holder.subHeader.setText(s);
holder.img.setImageResId(R.drawable.test);
return convertView;
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return data.get(position);
}
public long getItemId(int position) {
return position;
}
private static class PolicyViewHolder {
TextView header;
TextView subHeader;
ImageView img;
}
}
header_item
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp" >
<ImageView
android:id="#+id/list_item_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:src="#drawable/ic_launcher"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"
android:layout_marginLeft="5dp"
android:layout_toLeftOf="#+id/list_item_value"
android:layout_toRightOf="#+id/header_image"
android:orientation="vertical" >
<TextView
android:id="#+id/list_item_header"
style="#style/header_list_header"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/list_item_subheader"
style="#style/list_header_sub_header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="sub header" />
</LinearLayout>
</RelativeLayout>
i have tried to wrap a linearlayout="vertical" around this one as well
You have to tell the parent view how to stack your elememnts. This is necessary for parents like a LinearLayout. If you're going to have such an adapter, you need to have a parent to contain these things, UNLESS its a single view.
Update
Whenever you want to do processing with the views in a ListView you
need to create a custom adapter that will handle your logic
implementation and pass that information to the views as necessary.
A custom adater would inflate the views piece by piece, this can be
dynamic of fixed.
I suspect that your problem relates to Android simply not knowing how to handle the two levels of "scrollability" this design implies. Think about it - If the user drags over the header, how is Android supposed to know whether they mean to scroll the outer list or the list within the header? I once recall Romain Guy making the same point about placing ListViews inside ScrollViews, it's slightly meaningless.
What's probably happening is that Android makes the header big enough to simply display a single header list item and it assumes any dragging gesture by the user should apply to the outer list.
Generally, I think what you've described sounds like a bad design choice and you need to take a step back.
What functionally do you want this UI to do?
If it's simply that you want to display two sets of content within a single list, then this is a problem you need to solve within the ListAdapter implementation you're using. e.g. Take a look Jeff Sharkey's blog post on his SeparatedListAdapter.
Make a LinearLayout with vertical orientation and add both ListViews there. That should fix your hiccup.
Cheers.
I'm completely new to Java/Android and am stuck with listviews.
What I want is to have 4 lines in a row in listview with different font styles
rowlayout.xml
<TextView
android:id="#+id/1"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/2"
android:textSize="30sp"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/3"
android:typeface="sans"
android:textSize="20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/4"
android:typeface="sans"
android:textSize="15sp"
android:textStyle="italic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
I have this in a separate xml file
results.xml
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#id/TitleLbl" >
</Listview>
and my array adapter looks like this
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.rowlayout, R.id.2, Array);
setListAdapter(adapter);
What I'm trying to do is get an arraylist (containing ID, name, surname and number) to populate the listview so that each information is on its own line in the row.
the array adapter above works, but each of the four informations is in their own row.
Can anyone help?
(also, I've scoured the internet to try and sort this out, but can't seem to find anything that helps me)
You may need to use custom list view with custom array adapter. Refer this link for example.
Content:
The Android HelloListView ( http://developer.android.com/resources/tutorials/views/hello-listview.html ) tutorial shows how to bind a ListView to an array of string objects, but you'll probably outgrow that pretty quickly. This post will show you how to bind the ListView to an ArrayList of custom objects, as well as create a multi-line ListView.
Let's say you have some sort of search functionality that returns a list of people, along with addresses and phone numbers. We're going to display that data in three formatted lines for each result, and make it clickable.
First, create your new Android project, and create two layout files. Main.xml will probably already be created by default, so paste this in:
<?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_height="wrap_content"
android:text="Custom ListView Contents"
android:gravity="center_vertical|center_horizontal"
android:layout_width="fill_parent" />
<ListView
android:id="#+id/ListView01"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</LinearLayout>
Next, create a layout file called custom_row_view.xml. This layout will be the template for each individual row in the ListView. You can use pretty much any type of layout - Relative, Table, etc., but for this we'll just use Linear:
<?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:id="#+id/name"
android:textSize="14sp"
android:textStyle="bold"
android:textColor="#FFFF00"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView android:id="#+id/cityState"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView android:id="#+id/phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Now, add an object called SearchResults. Paste this code in:
public class SearchResults {
private String name = "";
private String cityState = "";
private String phone = "";
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setCityState(String cityState) {
this.cityState = cityState;
}
public String getCityState() {
return cityState;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getPhone() {
return phone;
}
}
This is the class that we'll be filling with our data, and loading into an ArrayList.
Next, you'll need a custom adapter. This one just extends the BaseAdapter, but you could extend the ArrayAdapter if you prefer.
public class MyCustomBaseAdapter extends BaseAdapter {
private static ArrayList<SearchResults> searchArrayList;
private LayoutInflater mInflater;
public MyCustomBaseAdapter(Context context, ArrayList<SearchResults> results) {
searchArrayList = results;
mInflater = LayoutInflater.from(context);
}
public int getCount() {
return searchArrayList.size();
}
public Object getItem(int position) {
return searchArrayList.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.custom_row_view, null);
holder = new ViewHolder();
holder.txtName = (TextView) convertView.findViewById(R.id.name);
holder.txtCityState = (TextView) convertView.findViewById(R.id.cityState);
holder.txtPhone = (TextView) convertView.findViewById(R.id.phone);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.txtName.setText(searchArrayList.get(position).getName());
holder.txtCityState.setText(searchArrayList.get(position).getCityState());
holder.txtPhone.setText(searchArrayList.get(position).getPhone());
return convertView;
}
static class ViewHolder {
TextView txtName;
TextView txtCityState;
TextView txtPhone;
}
}
(This is basically the same as the List14.java API demo)
Finally, we'll wire it all up in the main class file:
public class CustomListView extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ArrayList<SearchResults> searchResults = GetSearchResults();
final ListView lv1 = (ListView) findViewById(R.id.ListView01);
lv1.setAdapter(new MyCustomBaseAdapter(this, searchResults));
lv1.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Object o = lv1.getItemAtPosition(position);
SearchResults fullObject = (SearchResults)o;
Toast.makeText(ListViewBlogPost.this, "You have chosen: " + " " + fullObject.getName(), Toast.LENGTH_LONG).show();
}
});
}
private ArrayList<SearchResults> GetSearchResults(){
ArrayList<SearchResults> results = new ArrayList<SearchResults>();
SearchResults sr1 = new SearchResults();
sr1.setName("John Smith");
sr1.setCityState("Dallas, TX");
sr1.setPhone("214-555-1234");
results.add(sr1);
sr1 = new SearchResults();
sr1.setName("Jane Doe");
sr1.setCityState("Atlanta, GA");
sr1.setPhone("469-555-2587");
results.add(sr1);
sr1 = new SearchResults();
sr1.setName("Steve Young");
sr1.setCityState("Miami, FL");
sr1.setPhone("305-555-7895");
results.add(sr1);
sr1 = new SearchResults();
sr1.setName("Fred Jones");
sr1.setCityState("Las Vegas, NV");
sr1.setPhone("612-555-8214");
results.add(sr1);
return results;
}
}
Notice that we first get an ArrayList of SearchResults objects (normally this would be from an external data source...), pass it to the custom adapter, then set up a click listener. The listener gets the item that was clicked, converts it back to a SearchResults object, and does whatever it needs to do.