How to align strings to use in a listview?

12

In my Android project I need to create a table with a listview but the data always comes misaligned. I put each record in my database at a position in an array of strings so I can use it in listview . The method I use to try to align is this:

public static String CompletaEspacos(String palavra) {
    if (palavra == null) {
        palavra = "";
    }
    String retorno = "";

    palavra = palavra.trim();

    if(palavra.length()>=19){
        retorno = palavra.substring(0,19);
    } else {
        retorno = String.format("%-19s", palavra);
    }       
    return retorno;
}

In other words, each "cell" of the table contains a word until its 19th character or a smaller word with spaces until it reaches 19. That is my logic, but it is not working. What is the best way to create the strings of an array to mount an aligned table in listview in Java.

    
asked by anonymous 27.01.2014 / 18:01

2 answers

9

For this you need to use monospaced fonts, such as Courier (or the native Droid Sans Mono as pointed out by @Alexandre Marcondes).

Monospaced fonts, unlike proportional fonts, are those in which all letters have the same widths. See the comparison:

Example 1

XMILSW
WWMWMW
i01 .m

Example 2

XMILSW
WWMWMW
i01 .m

Notice that in the first case the letters do not align and the second one does.

Take a look at the typeface MONOSPACE documentation to see some options for that.

  

Consider the Grid View instead. Grid View allows you to have multiple separate columns, aligned regardless of content.

    
28.01.2014 / 16:44
8

Based on the comments, I could understand that what you want is a dynamic ListView. For this, you will need to create a Adapter specifically for this and fill each line of ListView with a specific xml, suitable for alignment.

To help, I found this tutorial that the author himself writes to be a good solution when filling a ListView with data from a database.

I've edited his code to stay a bit more generic, I'll split it into parts:

List class

package com.dynalist;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class MyList extends Activity {
    /** Called when the activity is first created. */
    ListView listView;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        listView = (ListView) findViewById(R.id.lv_country);
        listView.setAdapter(new EfficientAdapter(this));
    }
    private static class EfficientAdapter extends BaseAdapter {
        private LayoutInflater mInflater;

        public EfficientAdapter(Context context) {
            mInflater = LayoutInflater.from(context);
        }

        public int getCount() {
            return CountriesList.abbreviations.length;
        }

        public Object getItem(int position) {
            return 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.two_col_row, null);
                holder = new ViewHolder();
                holder.text1 = (TextView) convertView
                        .findViewById(R.id.TextView01);
                holder.text2 = (TextView) convertView
                        .findViewById(R.id.TextView02);

                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            holder.text1.setText(CountriesList.abbreviations[position]);
            holder.text2.setText(CountriesList.countries[position]);

            return convertView;
        }

        static class ViewHolder {
            TextView text1;
            TextView text2;
        }
    }
}

Disrupting this class we have:

private ListView listView;
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    listView = (ListView) findViewById(R.id.lv_country);
    listView.setAdapter(new EfficientAdapter(this));
}

In this section it creates the list from a predefined layout and saves the reference in the variable ListView to use later, next to it it assigns a Adapter to this list, which is defined internally of the class in this example (for code organization issues this is not the most correct way to do it, what would be correct to encapsulate the class and import it). Adapter is responsible for the contents of the list, when you assign%% of%, you are assigning the "data background". Retrieved from the Google Developers ListView documentation , treating the parameter Adapter of type adapter :

  

The ListAdapter which is responsible for maintaining the data backing this list and for producing a view to represent an item in that data set.

Free translation:

  

The ListAdapter which is responsible for maintaining the data in this list and for producing a view to represent an item that is in the dataset.

Within the class ListAdapter it creates some auxiliary methods, but the main method is EfficientAdapter :

public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.two_col_row, null);
        holder = new ViewHolder();
        holder.text1 = (TextView) convertView
            .findViewById(R.id.TextView01);
        holder.text2 = (TextView) convertView
            .findViewById(R.id.TextView02);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    } 
    holder.text1.setText(CountriesList.abbreviations[position]);
    holder.text2.setText(CountriesList.countries[position]); 
    return convertView;
}

With this method it initializes A LINE from getView , as discussed earlier. Each line is a view with two ListView of layout TextView , which will be shown below.

But how does he populate the list?

The "worm" is in methods two_col_rol , getCount and getItem , which causes it to iterate through all its entries (in this case a list of country abbreviations), allowing, from a vector , it populates the entire list with getItemId .

List XML

In the example it puts a header and a "line of subtitles", I preferred to treat only getView of XML so the answer does not get longer.

<?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"
    android:background="#ffccd0"
    >
    <ListView
        android:id="@+id/lv_country"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:cacheColorHint="#00000000">
    </ListView>
</LinearLayout>

All it does is ListView normal that does not need much attention, since it is a basic list, there is not much to comment on.

The view of each line of the List

Here's where the other "secret" to making a dynamic list aligned. Since each line is a ListView , you just have to align the text from View as shown in android:gravity below:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:gravity="left|center"
    android:layout_width="wrap_content"
    android:paddingBottom="10px"
    android:paddingTop="10px"
    android:paddingLeft="3px">
     <!-- Coluna 1 -->
     <TextView
        android:id="@+id/TextView01"
        android:layout_width="70dip"
        android:layout_height="wrap_content"
        android:gravity="left"
        android:textSize="15dip"
        android:textStyle="bold"
        android:textColor="#d08021"
        android:paddingLeft="20dip"/>
     <!--Coluna 2-->
     <TextView
        android:id="@+id/TextView02"
        android:layout_width="200dip"
        android:layout_height="wrap_content"
        android:gravity="left"
        android:layout_marginLeft="10dip"
        android:textSize="15dip"
        android:textStyle="bold"
        android:textColor="#7f0000"/>
</LinearLayout>

Since, in your case, you only need one column, you just have to leave a XML , with the formatting you want.

    
27.01.2014 / 18:43