I'm trying to create a list in Android in which each item has one ore more action buttons, as it's shown here with the number 2:
Is there any predefined way or template to do this, or do I have to manually create the views for the items in the list with their separators, action buttons and everything? (if that is the case, I would also appreciate some help with it :))
Thanks!
You'll have to create your own layout for the rows. (You shouldn't need to do the separators.)
I do this in one of my apps. Here's one of the layouts I use for my items:
<?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">
<ImageView
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:contentDescription="#string/contentDescription_itemIcon"
android:src="#drawable/album_placeholder" />
<Button
android:id="#+id/playButton"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:focusable="false"
android:focusableInTouchMode="false" />
<Button
android:id="#+id/queueButton"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#id/playButton"
android:focusable="false"
android:focusableInTouchMode="false" />
<TextView
android:id="#+id/mainText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="4dp"
android:layout_toLeftOf="#id/queueButton"
android:layout_toRightOf="#id/icon"
android:text="#string/placeholder_mainText" />
<TextView
android:id="#+id/rightAdditionalText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#id/leftAdditionalText"
android:layout_marginRight="4dp"
android:layout_toLeftOf="#id/queueButton"
android:text="#string/placeholder_rightText" />
<TextView
android:id="#+id/leftAdditionalText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#id/mainText"
android:layout_below="#id/mainText"
android:layout_marginTop="0dp"
android:layout_toLeftOf="#id/rightAdditionalText"
android:text="#string/placeholder_leftText" />
</RelativeLayout>
Here's the adapter I use:
private class ItemAdapter extends ArrayAdapter<T> {
private int rowLayoutId;
public ItemAdapter(Context context, int rowLayoutId, T[] items) {
super(context, 0, items);
this.rowLayoutId = rowLayoutId;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(rowLayoutId, null);
v.findViewById(R.id.queueButton).setOnClickListener(onQueueButtonClicked);
v.findViewById(R.id.playButton).setOnClickListener(onPlayButtonClicked);
}
T item = getItem(position);
if (item != null) {
setText(v, R.id.mainText, item.name);
fillRowView(v, item);
}
v.setTag(item);
return v;
}
}
Mine is parameterized with the row layout id for all items, but you may want to do that differently. The setText() and fillRowView() functions are helpers defined in the containing class.
Note that I set the item object into the row view's tag, so I can get it later in the button click handler:
View.OnClickListener onPlayButtonClicked = new View.OnClickListener() {
#Override
public void onClick(View button) {
View listItem = (View)button.getParent();
Object tag = listItem.getTag();
try {
#SuppressWarnings("unchecked")
T item = (T)tag;
// do someting with item
}
catch (ClassCastException e) {
}
}
};
You can see what this looks like here
Related
I'm building an app for a news website, I have created a ListView and a layout for each item, which has quite a bit of white space, but on the list view all the white space is removed.
Here's what I mean: http://imgur.com/a/mLuuE
This is an item layout:
<?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="175dp"
android:gravity="center"
android:layout_weight="0"
android:id="#+id/article_layout"
android:background="#drawable/gradientdemo">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center|bottom"
android:orientation="vertical"
android:paddingLeft="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="Titolo dell'articolo"
android:textSize="#dimen/abc_text_size_headline_material"
android:layout_gravity="left"
android:id="#+id/article_title" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="3/9/16 - Autore"
android:layout_gravity="left"
android:id="#+id/article_info" />
</LinearLayout>
</LinearLayout>
This is my custom adapter:
public class ArticleAdapter extends ArrayAdapter<Article> {
public ArticleAdapter(Context context, int textViewResourceId){
super(context, textViewResourceId);
}
public ArticleAdapter(Context context, int resource, List<Article> items ){
super(context, resource, items);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.article_item, null);
}
Article article = (Article) getItem(position);
TextView title = (TextView) v.findViewById(R.id.article_title);
TextView info = (TextView) v.findViewById(R.id.article_info);
if( title != null ) {
title.setText( article.getTitle() );
}
if( info != null ) {
info.setText( article.getAuthor() );
}
return v;
}
}
Hope it's readable, I'm kind of new to android development.
Your cell's LineaerLayout:
android:layout_height="0dp"
android:layout_weight="1"
change to:
android:layout_height="wrap_content"
you don't need layout_weight
Delete the android:layout_weight="1" and add a correct height, e.g. android:layout_height="60dp":
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center|bottom"
android:orientation="vertical"
android:paddingLeft="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="Titolo dell'articolo"
android:textSize="#dimen/abc_text_size_headline_material"
android:layout_gravity="left"
android:id="#+id/article_title" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="3/9/16 - Autore"
android:layout_gravity="left"
android:id="#+id/article_info" />
</LinearLayout>
in the linearLayout use wrapcontent, erase layout_weigth and add weigthsum=1
Then in textViews change height to 0dp and add to each one layout_weight=0.5
I think this will work
I fixed this by changing this line in the adapter
v = vi.inflate(R.layout.article_item, null);
to this one:
v = vi.inflate(R.layout.article_item, parent, false);
I have a list that when you click on the row on the right side the layout with the icon is changed by other. This makes it well but when I scrolling in the list, I notice there are rows with the same icon without do click. Also, if I scroll quickly these same icons are lost and are built differently. I think it's on the reuse of cells but I can not find the solution. What I want is that the image stays active only in the row where clicka.
Thanks!!
Adapter class:
public class ListadoVotantesArrayAdapter extends ArrayAdapter<Votante> {
private Context context;
private LayoutInflater inflater;
private ArrayList<Votante> listaVotantes;
private int rowLayout;
private View mConverView;
public ListadoVotantesArrayAdapter(Context context, int resource, ArrayList<Votante> objects) {
super(context, resource,objects);
this.context = context;
this.inflater = LayoutInflater.from(context);
this.listaVotantes = objects;
this.rowLayout = resource;
}
public int getCount(){
return this.listaVotantes.size();
}
public Votante getVotante(int position){
return this.listaVotantes.get(position);
}
private static class ViewHolder {
public TextView lblName;
public TextView lblLastName;
public TextView lblDni;
public TextView lblVoterNumber;
public RelativeLayout lytVoted;
public RelativeLayout lytCanVote;
public RelativeLayout lytUndo;
}
public View getView(int position, View converView, ViewGroup parent) {
final ViewHolder viewHolder;
mConverView = converView;
if (mConverView == null){
viewHolder = new ViewHolder();
this.mConverView = inflater.inflate(this.rowLayout, parent, false);
if (mConverView != null){
viewHolder.lblName = (TextView) mConverView.findViewById(R.id.lblVoterName);
viewHolder.lblLastName = (TextView) mConverView.findViewById(R.id.lblVoterLastName);
viewHolder.lblDni = (TextView) mConverView.findViewById(R.id.lblDni);
viewHolder.lblVoterNumber = (TextView) mConverView.findViewById(R.id.lblNumber);
viewHolder.lytVoted = (RelativeLayout) mConverView.findViewById(R.id.lytVoted);
viewHolder.lytCanVote = (RelativeLayout) mConverView.findViewById(R.id.lytCanVote);
viewHolder.lytUndo = (RelativeLayout) mConverView.findViewById(R.id.lytUndo);
mConverView.setTag(viewHolder);
}
}else{
viewHolder = (ViewHolder) mConverView.getTag();
}
Votante votante = getVotante(position);
viewHolder.lblName.setText(votante.getNombre());
viewHolder.lblLastName.setText(votante.getApellidos());
viewHolder.lblDni.setText(votante.getDni());
viewHolder.lblVoterNumber.setText(""+votante.getNumVotante());
if (votante.getVotado()){
viewHolder.lytVoted.setVisibility(View.VISIBLE);
viewHolder.lytCanVote.setVisibility(View.GONE);
}else{
viewHolder.lytVoted.setVisibility(View.GONE);
viewHolder.lytCanVote.setVisibility(View.VISIBLE);
}
mConverView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewHolder.lytUndo.setVisibility(View.VISIBLE);
notifyDataSetChanged();
}
});
return mConverView;
}
}
Layout Row:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/lyt_voter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="1dp">
<RelativeLayout
android:id="#+id/lytVoterNumber"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_alignParentLeft="true"
android:background="#color/lightBlueItemList">
<TextView
android:id="#+id/lblNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="1999"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
<LinearLayout
android:id="#+id/lytVoterData"
android:layout_width="wrap_content"
android:layout_height="70dp"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/lytCanVote"
android:layout_toRightOf="#+id/lytVoterNumber"
android:layout_toStartOf="#+id/lytCanVote"
android:background="#color/whiteItemList"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="#+id/lblVoterLastName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Suarez Garcia de la Serna"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/lblVoterName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="José Carlos"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/lblDni"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="44950962S"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
<RelativeLayout
android:id="#+id/lytCanVote"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_alignParentRight="true"
android:background="#color/yellowItemList"
android:minHeight="30dp"
android:minWidth="30dp">
<ImageView
android:id="#+id/imgVote"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/flecha" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/lytVoted"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_alignParentRight="true"
android:background="#color/grrenAcceptList"
android:minHeight="30dp"
android:minWidth="30dp"
android:visibility="gone">
<ImageView
android:id="#+id/imgAccept"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/aceptar"
/>
</RelativeLayout>
<RelativeLayout
android:layout_width="70dp"
android:layout_height="70dp"
android:minHeight="30dp"
android:minWidth="30dp"
android:background="#color/redD3"
android:id="#+id/lytUndo"
android:layout_alignParentRight="true"
android:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imgUndo"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#drawable/undo"/>
</RelativeLayout>
</RelativeLayout>
You need to follow below Idea
1) this line of code mConverView = converView; doesn't makes sense. directly use converView(View from getView param). Remove mConvertView from the adapter.
2) Add some mechanism which can tell you which row is clicked and save that variable.
Example:- Have an boolean Array of size Rows.size . and set them in onClick.
Boolean[] array = new Boolean[getSize()];
in onClick that you already have in your getview set this.
public void onClick(View v) {
array[position] = !array[position];
viewHolder.lytUndo.setVisibility(View.VISIBLE);
//You do not need to call notifyDatasetChange.
3) in getView(), when you are setting data in to row items/or just before onClick. have a check like below.
if(array[position])// this will tell you if you need to show or hid lytUndo thing
viewHolder.lytUndo.setVisibility(View.VISIBLE); // Show it
else
viewHolder.lytUndo.setVisibility(View.GONE); // hide it or do whatever you want
You might need to set some params as final
I have written this as simple as possible, comment back with your result.
I'm stumped. This one IS simple and I'm missing something simple but I'm just not getting anywhere.
I have a ListView that contains pretty simple items - TextView's that contain text of the form "N. name", where N is the position in the list and name is the name of the associated objects. I've created a ListAdapter that presents that information into the ListView.
The presentation stuff seems to work fine. It's the part where when I tap on a row that's not working. I just don't get a notification. If I set a onClickListener on the item (when it's generated in the Adapter) I do get a notification, but it's convoluted to make that work the way I'd like it to. I've tried a bunch of stuff - changing descendent focusability, enabling, disabling, setting itemsCanFocus to false, ... - but no luck on any of them.
I've included relevant code for configuring the view and the elements in the ListView.
In particular, what I'm trying to do is get that OnItemClickLister.onItemClick() to get invoked when I tap on a row. Any thoughts on what I'm doing wrong?
Activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model = FZMModel.getInstance(this);
setContentView(R.layout.activity_deploy);
TextView viewTitle = (TextView) findViewById(R.id.deploy_header);
if (model.getProfiles().size() == 0) {
viewTitle.setText(R.string.deploy_header_create);
} else {
viewTitle.setText(R.string.deploy_header_choose);
}
profileListView = (ListView) findViewById(R.id.profileListView);
profileListAdapter = new ProfileListAdapter(this, model);
profileListView.setAdapter(profileListAdapter);
profileListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Log.d(TAG, String.format("Item %d selected (with id=0x%x)", position, id));
}
});
}
Adapter:
... relevant code from getView():
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final Profile profile = model.getProfileAtIndex(position);
final int rowNum = position;
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.profile_list_layout, parent, false);
}
TextView profileIndexView;
TextView profileNameView;
profileIndexView = (TextView) convertView.findViewById(R.id.profileIndexLabel);
profileNameView = (TextView) convertView.findViewById(R.id.profileNameLabel);
profileIndexView.setText(String.format("%d.", position));
profileNameView.setText(profile.getName());
// convertView.setOnClickListener(new View.OnClickListener() {
// #Override
// public void onClick(View view) {
// Toast.makeText(context, String.format("Did select row #%d (index=%d)",rowNum, profile.getPosition()), Toast.LENGTH_SHORT).show();
// }
// });
return convertView;
}
activity layout:
<RelativeLayout 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"
tools:context="com.nsn.flexizonemobile.FZMConcreteActionDeploy"
tools:ignore="MergeRootFrame" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="#string/deploy_header_choose"
android:id="#+id/deploy_header"
android:layout_margin="10dp"
android:layout_centerHorizontal="true" />
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/profileListView"
android:layout_gravity="left|top"
android:layout_alignParentLeft="true"
android:layout_marginLeft="0dp"
android:choiceMode="none"
android:layout_below="#+id/deploy_header"
android:divider="#android:color/darker_gray"
android:dividerHeight="2dp"
android:clickable="true"
android:descendantFocusability="beforeDescendants" />
</RelativeLayout>
profile_list_layout layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="#dimen/profile_index_width"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="A. "
android:id="#+id/profileIndexLabel"
android:gravity="center_vertical|right"
android:layout_centerVertical="true"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:textSize="24sp"
android:textIsSelectable="true"
android:layout_alignParentStart="false"
android:layout_alignParentTop="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Profile Name"
android:id="#+id/profileNameLabel"
android:layout_alignParentLeft="false"
android:layout_alignParentTop="false"
android:gravity="center_vertical"
android:layout_toRightOf="#+id/profileIndexLabel"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:textSize="24sp"
android:paddingTop="10dp"
android:paddingBottom="10dp" />
</RelativeLayout>
in the textview of your inflator layout just add:
android:focusable="false"
android:focusableInTouchMode="false"
and in parent layout of your inflator i.e in relative layout of inflator add:
android:descendantFocusability="blocksDescendants"
remove :
android:descendantFocusability="beforeDescendants"
from your listview. and set height of your listview to match_parent will solve your issue.
remove following attributes from your ListView:
android:choiceMode="none"
android:clickable="true"
android:descendantFocusability="beforeDescendants"
also
android:layout_width="wrap_content"
android:layout_height="wrap_content"
makes no sense in this context (especially height)
I'm a beginner to Android development, but not to software development. I've been looking for tutorials on how to create dynamic ListViews with images and have had some trouble.
The tutorial I followed most closely was #2 on this link (the Custom ArrayAdapter example): http://www.mkyong.com/android/android-listview-example/
This works fine if I remove the header and footer from my layout xml file, but I really need those to be included. Below I'll post my source from my Activity java file, my custom array adapter java file, and my layout xml file as well as the output. I think there may be something I'm missing or not understanding about how the layout inflater works.
Thanks for your time.
MainActivity.java
public class MainActivity extends ListActivity {
static final String[] MAIN_MENU =
new String[] { "ICD-10", "EDUCATION", "NEWS", "SERVICES", "CONTACT" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ImageAdapter(this, MAIN_MENU));
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
//get selected items
String selectedValue = (String) getListAdapter().getItem(position);
// to contact
if(selectedValue.equals(MAIN_MENU[4])) {
contactPressed(v);
}
// to icd-10
else if(selectedValue.equals(MAIN_MENU[0])) {
startActivity(new Intent(MainActivity.this, ICDActivity.class));
}
// to services
else if(selectedValue.equals(MAIN_MENU[3])) {
startActivity(new Intent(MainActivity.this, ServicesActivity.class));
}
}
public void contactPressed(View v) {
startActivity(new Intent(MainActivity.this, ContactActivity.class));
overridePendingTransition(R.anim.slide_in_up, R.anim.stay);
}
}
ImageAdapter.java
public class ImageAdapter extends ArrayAdapter<String>
{
private final Context context;
private final String[] values;
public ImageAdapter(Context context, String[] values) {
super(context, R.layout.activity_main, 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.activity_main, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.lvText);
ImageView imageView = (ImageView) rowView.findViewById(R.id.lvImage);
textView.setText(values[position]);
// Change icon based on name
String s = values[position];
if (s.equals("ICD-10"))
{
imageView.setImageResource(R.drawable.icon_icd10);
}
else if(s.equals("EDUCATION"))
{
imageView.setImageResource(R.drawable.icon_education);
}
else if(s.equals("NEWS"))
{
imageView.setImageResource(R.drawable.icon_news);
}
else if(s.equals("SERVICES"))
{
imageView.setImageResource(R.drawable.icon_services);
}
else if(s.equals("CONTACT"))
{
imageView.setImageResource(R.drawable.icon_contact);
}
return rowView;
}
}
activity_main.xml
<RelativeLayout 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" >
<ImageView
android:id="#+id/custom_background"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitXY"
android:src="#drawable/gray">
</ImageView>
<RelativeLayout
android:id="#+id/headerLayout"
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_alignParentTop="true" >
<ImageView
android:id="#+id/header"
android:layout_width="wrap_content"
android:layout_height="45dp"
android:scaleType="fitXY"
android:src="#drawable/logo_header" />
</RelativeLayout>
<!-- Footer aligned to bottom -->
<RelativeLayout
android:id="#+id/footerLayout"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="30dp" >
<ImageView
android:id="#+id/footer"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="30dp"
android:scaleType="center"
android:src="#drawable/footer" />
<TextView
android:id="#+id/footerText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="14dp"
android:onClick="contactPressed"
android:layout_marginBottom="5dp"
android:text="#string/footerText" />
</RelativeLayout>
<ScrollView
android:id="#+id/scrollableContents"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#id/footerLayout"
android:layout_below="#id/headerLayout" >
<LinearLayout
android:id="#+id/linearList"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#id/footerLayout"
android:layout_below="#id/headerLayout"
android:padding="5dp"
tools:context=".MainActivity" >
<!-- Making a dynamic ListView with images with the two attributes below -->
<ImageView
android:id="#+id/lvImage"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentRight="true"
android:layout_marginLeft="20dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:src="#drawable/icon_icd10" >
</ImageView>
<TextView
android:id="#+id/lvText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#+id/lvText"
android:textSize="25sp" >
</TextView>
</LinearLayout>
</ScrollView>
</RelativeLayout>
The output I get for this is:
If I comment out the header and footer code in the xml I get:
The goal is for it to look similar to this but with images on the right side of each line:
Thanks for your time.
First looks like you have
android:layout_above="#id/footerLayout"
android:layout_below="#id/headerLayout"
on your #+id/scrollableContents, which is good. But you also have it on the view nested inside it, #+id/linearList which is not right. There may be other layout problems but it is hard to tell. In general this layout looks very complex for what you are trying to achieve.
But I'm not sure really what you mean by "dynamic ListView" and it looks like you are trying to re-create the functionality of a listview using a ScrollView. I don't think you should take that approach. The ListView is very flexible and you can use a custom layout for your items.
So I found the solution to my problem while searching for another tutorial. I finally ended up using this tutorial: http://www.learn2crack.com/2013/10/android-custom-listview-images-text-example.html
My problem was that I tried to replace my ListView with a TextView and ImageView in the same layout.xml file when I should have created my TextView and ImageView in a different layout.xml file. Below is the final code and the correct output I was looking for. Thanks!
list_single.xml (below)
<?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" >
<ImageView
android:id="#+id/img"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginRight="5dp"
android:layout_marginTop="9dp"
android:layout_alignParentRight="true" />
<TextView
android:id="#+id/txt"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginTop="17dp"
android:layout_marginLeft="5dp"
android:textSize="23sp" />
</RelativeLayout>
activity_main.xml (below)
<RelativeLayout 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" >
<ImageView
android:id="#+id/custom_background"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitXY"
android:src="#drawable/gray">
</ImageView>
<ImageView
android:id="#+id/header"
android:layout_width="wrap_content"
android:layout_height="45dp"
android:scaleType="fitXY"
android:src="#drawable/logo_header" />
<!-- Footer aligned to bottom -->
<ImageView
android:id="#+id/footer"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_alignParentBottom="true"
android:scaleType="center"
android:src="#drawable/footer" />
<TextView
android:id="#+id/footerText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="5dp"
android:layout_marginLeft="14dp"
android:onClick="contactPressed"
android:text="#string/footerText" />
<ListView
android:id="#+id/mainMenuList"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#id/footer"
android:layout_below="#id/header"
android:divider="#000000"
android:dividerHeight="0.1dp" />
</RelativeLayout>
ImageAdapter.java (below)
public class ImageAdapter extends ArrayAdapter<String>
{
private final Context context;
private final String[] values;
public ImageAdapter(Context context, String[] values) {
super(context, R.layout.list_single, 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.list_single, null, true);
TextView textView = (TextView) rowView.findViewById(R.id.txt);
ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
textView.setText(values[position]);
// Change icon based on name
String s = values[position];
if (s.equals("ICD-10"))
{
imageView.setImageResource(R.drawable.icon_icd10);
}
else if(s.equals("EDUCATION"))
{
imageView.setImageResource(R.drawable.icon_education);
}
else if(s.equals("NEWS"))
{
imageView.setImageResource(R.drawable.icon_news);
}
else if(s.equals("SERVICES"))
{
imageView.setImageResource(R.drawable.icon_services);
}
else if(s.equals("CONTACT"))
{
imageView.setImageResource(R.drawable.icon_contact);
}
return rowView;
}
}
MainActivity.java (below)
public class MainActivity extends Activity {
ListView list;
static final String[] MAIN_MENU =
new String[] { "ICD-10", "EDUCATION", "NEWS", "SERVICES", "CONTACT" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = (ListView)findViewById(R.id.mainMenuList);
list.setAdapter(new ImageAdapter(MainActivity.this, MAIN_MENU));
// register onClickListener to handle click events on each item
list.setOnItemClickListener(new OnItemClickListener() {
// argument position gives the index of item which is clicked
public void onItemClick(AdapterView<?> arg0, View v, int position,
long arg3) {
String selectedValue = MAIN_MENU[position];
// to contact
if(selectedValue.equals(MAIN_MENU[4])) {
contactPressed(v);
}
// to icd-10
else if(selectedValue.equals(MAIN_MENU[0])) {
startActivity(new Intent(MainActivity.this, ICDActivity.class));
}
// to services
else if(selectedValue.equals(MAIN_MENU[3])) {
startActivity(new Intent(MainActivity.this, ServicesActivity.class));
}
}
});
}
public void contactPressed(View v) {
startActivity(new Intent(MainActivity.this, ContactActivity.class));
overridePendingTransition(R.anim.slide_in_up, R.anim.stay);
}
}
And the final output (below)
I am writing an app that requires the user to enter some details into a form. The form initially has 3 EditText views in a row. When the user enters some data in the last editText, the onFocusChangeListener should initiate a new row.
This is what I want to do.
How can I create 3 editText views in a single listView row at runtime?
To create a listView with multiple views in a row, you need to customize your adapter, so it can take the form of your row from a source XML -that you should create- and puts it into your listView, here is an example based on BaseAdapter:
This is your Xml source that contains the form of your Row:
espaceclientuploadsource.xml :
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:addStatesFromChildren="true" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:addStatesFromChildren="true" >
<ImageView
android:id="#+id/Uplodimage"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="15dp"
android:src="#drawable/bingo" />
<TextView
android:id="#+id/UploadedProductName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="24dp"
android:layout_toRightOf="#+id/Uplodimage"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/UplodedProductPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/UploadedProductName"
android:layout_below="#+id/UploadedProductName"
android:layout_marginTop="16dp"
android:text="Small Text"
android:textAppearance="?android:attr/textAppearanceSmall" />
<ImageView
android:id="#+id/UploadedStatus"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_above="#+id/UplodedProductPrice"
android:layout_alignParentRight="true"
android:layout_alignTop="#+id/UploadedProductName"
android:layout_marginRight="27dp"
android:src="#drawable/bingo" />
<ImageView
android:id="#+id/ImageViewDelete"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_alignBottom="#+id/UplodedProductPrice"
android:layout_alignLeft="#+id/UploadedStatus"
android:clickable="true"
android:src="#drawable/bingo" />
</RelativeLayout>
Then you need to create an XML file that containes your ListView:
espaceclientuploads:
<EditText
android:id="#+id/login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" >
<requestFocus />
</EditText>
<EditText
android:id="#+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPassword" />
<Button
android:id="#+id/submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="submit"
android:text="Button" />
</LinearLayout>
Next is your adapter, it's role is to use your sourceXML as your row Format,
UploadedAdapter :
public class UploadedAdapter extends BaseAdapter
{
List<Article> lesArticles;
DataSource produitSource;
LayoutInflater inflater;
String path= Environment.getExternalStorageDirectory().toString()+File.separator+"Bingo";
public UploadedAdapter(Context context, List<Article> lesArticles)
{
inflater=LayoutInflater.from(context);
this.lesArticles = lesArticles;
}
#Override
public int getCount()
{
return lesArticles.size();
}
#Override
public Object getItem(int position)
{
return lesArticles.get(position);
}
#Override
public long getItemId(int position)
{
return position;
}
private class ViewHolder
{
TextView nomduProduit;
TextView prixDuProduit;
ImageView status;
ImageView imageDuProduit;
ImageView delete;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView==null)
{
holder=new ViewHolder();
convertView = inflater.inflate(R.layout.espaceclientuploadsource, null);
holder.nomduProduit = (TextView)convertView.findViewById(R.id.UploadedProductName);
holder.prixDuProduit = (TextView)convertView.findViewById(R.id.UplodedProductPrice);
holder.imageDuProduit = (ImageView)convertView.findViewById(R.id.Uplodimage);
holder.status = (ImageView)convertView.findViewById(R.id.UploadedStatus);
holder.delete=(ImageView)convertView.findViewById(R.id.ImageViewDelete);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
Drawable drawableImage = new BitmapDrawable(bitmapImage);
holder.imageDuProduit.setImageDrawable(drawableImage);
holder.nomduProduit.setText(lesArticles.get(position).getNomArticle());
holder.prixDuProduit.setText(lesArticles.get(position).getPrix());
holder.delete.setImageResource(R.drawable.delete);
return convertView;
}
}
As you can see, your adapter extends the baseAdapter which is an abstract class, so you need to Override its method.
Finally it's your activity that will display your listView:
public class EspaceClientUplodedProducts extends Activity{
List<Article> lesArticle= new ArrayList<Article>();
ListView lvListe;
UploadedAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.espaceclientuploads);
lvListe= (ListView)findViewById(R.id.UploadListView);
adapter = new UploadedAdapter(this, lesArticle);
lvListe.setAdapter(adapter);
lvListe.setOnItemClickListener(this);
}
}