OK, so I'm mainly a C++ developer but I've been looking into making apps for Android. I haven't used Java before, or done much UI development, so it's a lot to take in at the moment.

There is a question at the end of this, skip to it if you feel like it. The following is mostly background details...

Anyway, for my app, I require the ability to make a vertical scrolling list of elements. Each element should have the same layout, but I'd like to be able to have a number of elements laid out in each list element. So, something like this:

List:
    ListItem:
        Column:
            TickBox
        Column:
            Row: TitleText
            Row: DetailText
        Column:
            Image
    ListItem:
        Column:
            TickBox
        Column:
            Row: TitleText
            Row: DetailText
        Column:
            Image
            ... etc.

(I hope that's vaguely understandable). I don't know the number of items in the list at the time of writing the app (the user will create new items to go in the list).

OK, so after looking about a bit, I have the following scheme. A main activity (activity_main.xml) that looks like this:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context=".MainActivity" 
android:orientation="vertical">

<ListView
    android:id="@+id/android:list"
    android:layout_width="fill_parent"
 s   android:layout_height="fill_parent"
    />

<TextView
    android:id="@+id/android:empty"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:text="@string/click_to_add_task"
    />

</LinearLayout>

This has a main ListView, which the items will go in, and a TextView, which has some text in it. I found this example that seemed to do what I was looking for (or at least had a sensible-looking approach). So, each item has it's own XML that describes how an item in the list should be layed out:

<?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="?android:attr/listPreferredItemHeight"
    android:padding="6dip" >

   <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_marginRight="6dip"
        android:src="@drawable/ic_launcher"
        android:contentDescription="@string/null_string"
        />

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="0dip"
        android:layout_height="fill_parent"
        android:layout_weight="1" >

        <TextView
            android:id="@+id/toptext"
            android:orientation="vertical"
            android:layout_width="0dip"
            android:layout_height="fill_parent"
        />

        <TextView
            android:id="@+id/bottomtext"
            android:orientation="vertical"
            android:layout_width="0dip"
            android:layout_height="fill_parent"
            android:singleLine="true"
            android:ellipsize="marquee"
        />
    </LinearLayout>
</LinearLayout>

In order to use this layout XML for the items in the list, there is a custom TaskListView class (extends listView) and a custom TaskAdapter class (extends ArrayAdapter< Task >, Task is my class that holds details of each item in the list) that populates the list.

Finally, my ActivityMain.java looks like this:

package com.test.test1

import java.util.ArrayList;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ListActivity {    

    private ProgressDialog m_progDialog = null;
    private ArrayList< Task > m_tasks = null;
    private TaskAdapter m_adapter;

    @Override
    public void onCreate( Bundle savedInstanceState ) {
        super.onCreate( savedInstanceState );
        setContentView( R.layout.activity_main);

        m_tasks = new ArrayList< Task >();

        m_progDialog = ProgressDialog.show( MainActivity.this, "Please wait...", "Retrieving data...", true );

        getTasks();

        m_adapter = new TaskAdapter( this, R.layout.row, m_tasks );
        setListAdapter( m_adapter );

        m_adapter.notifyDataSetChanged();
        Log.d("ARRAY", " " + m_tasks.size() );
        for ( int i = 0; i < m_tasks.size(); i++ )
            m_adapter.add( m_tasks.get( i ) );

        m_progDialog.dismiss();
        m_adapter.notifyDataSetChanged();
    }

    public void getTasks() {
        try {
            m_tasks = new ArrayList< Task >();

            Task t1 = new Task();
            t1.setName("SF Services");
            t1.setStatus("Pending");

            Task t2 = new Task();
            t2.setName("SF Ads");
            t2.setStatus("Completed");

            m_tasks.add(t1);
            m_tasks.add(t2);
        }
        catch ( Exception e )
        {
            Log.e("BACKGROUD_PROC", e.getMessage() );
        }
    }

    private class TaskAdapter extends ArrayAdapter< Object >
    {
        private ArrayList< Task > m_items = new ArrayList< Task >();

        private Context m_context;

        public TaskAdapter( Context context, int textViewResourceId, ArrayList< Task > items ) {
            super( context, textViewResourceId );

            m_context = context;
            m_items = items;
        }

        @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( R.layout.row, null);
            }

            if ( m_items.size() > position )
            {
                Task task = m_items.get( position );
                if ( task != null ) {
                    TextView tt = (TextView) v.findViewById( R.id.toptext);
                    TextView bt = (TextView) v.findViewById( R.id.bottomtext);

                    if (tt != null)
                        tt.setText( "Name: " + task.getName());

                    if(bt != null)
                        bt.setText( "Status: " + task.getStatus() );

                    // (DEBUGGING) make an alert box that displays the values of the values in the text views
                    AlertDialog.Builder altDialog= new AlertDialog.Builder(m_context);
                    altDialog.setMessage( tt.getText().toString() + ": " + bt.getText().toString() ); // here add your message
                    altDialog.setNeutralButton( "OK", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(getApplicationContext(), "Ok button Clicked ", Toast.LENGTH_LONG).show();
                        }
                    });
                    altDialog.show();
                }
            }

            return v;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

}

So, the onCreate method of MainActivity does some "generic" bits first and then (on line 35) calls getTasks(). This populates the ArrayList of tasks with a couple of tasks. Then line 37 initialises the TaskAdapter, which doesn't do anything particularly suspicious. It then appears that the tasks get added to the adapter on line 43. At some point the method TaskAdapter.getView is called for each item in the list of tasks. I can see this happening because I made an alert box appear each time the method is called. The box (line 106) displays the text that should be in the finished view. I can indeed see the correct text in the alert. However, the text does not appear in the items of the list. My question (finally) is why not? My understanding is that the View returned by View.findViewById is a reference to a view (if my new understanding of Java is correct), so adding text to these TextView objects should affect the ones in the oringinal view that was passed into the function?

Sorry about the extremely long post! (I'm not sure which bits are crittical and which are superfluous)

Recommended Answers

All 2 Replies

In your "row.xml" file, change lines 25-26 and 32-33 from:

        android:layout_width="0dip"
        android:layout_height="fill_parent"

to:

        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

I tested this and it seemed to work fine after that little change.

Awesome. That did the job. Cheers :o)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.