Подтвердить что ты не робот

Добавление элемента подменю ListView в Android

Я создал RSS-ридер, в котором перечислены элементы в списке. Мне также нужна дата ниже каждого элемента, но я понятия не имею, как это сделать. Мне нужна помощь, чтобы текст Sub Item отображал pubDate, который был получен из RSS-канала.

Это код, который у меня есть для моего класса:

public class RSSReader extends Activity implements OnItemClickListener
{
    public final String RSSFEEDOFCHOICE = "http://app.calvaryccm.com/mobile/android/v1/devos";

    public final String tag = "RSSReader";
    private RSSFeed feed = null;

    /** Called when the activity is first created. */

    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);

        // go get our feed!
        feed = getFeed(RSSFEEDOFCHOICE);

        // display UI
        UpdateDisplay();
    }

    private RSSFeed getFeed(String urlToRssFeed)
    {
        try
        {
            // setup the url
           URL url = new URL(urlToRssFeed);

           // create the factory
           SAXParserFactory factory = SAXParserFactory.newInstance();
           // create a parser
           SAXParser parser = factory.newSAXParser();

           // create the reader (scanner)
           XMLReader xmlreader = parser.getXMLReader();
           // instantiate our handler
           RSSHandler theRssHandler = new RSSHandler();
           // assign our handler
           xmlreader.setContentHandler(theRssHandler);
           // get our data via the url class
           InputSource is = new InputSource(url.openStream());
           // perform the synchronous parse           
           xmlreader.parse(is);
           // get the results - should be a fully populated RSSFeed instance, or null on error
           return theRssHandler.getFeed();
        }
        catch (Exception ee)
        {
            // if we have a problem, simply return null
            System.out.println(ee.getMessage());
            System.out.println(ee.getStackTrace());
            System.out.println(ee.getCause());
            return null;
        }
    }
    public boolean onCreateOptionsMenu(Menu menu) 
    {
        super.onCreateOptionsMenu(menu);
        menu.add(Menu.NONE, 0, 0, "Refresh");
        Log.i(tag,"onCreateOptionsMenu");
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item){
        switch (item.getItemId()) {
        case 0:

            Log.i(tag,"Set RSS Feed");
            return true;
        case 1:
            Log.i(tag,"Refreshing RSS Feed");
            return true;
        }
        return false;
    }

    private void UpdateDisplay()
    {
        TextView feedtitle = (TextView) findViewById(R.id.feedtitle);
        TextView feedpubdate = (TextView) findViewById(R.id.feedpubdate);
        ListView itemlist = (ListView) findViewById(R.id.itemlist);


        if (feed == null)
        {
            feedtitle.setText("No RSS Feed Available");
            return;
        }

        if(feedtitle != null)
            feedtitle.setText(feed.getTitle());
        if(feedpubdate != null)
            feedpubdate.setText(feed.getPubDate());


        ArrayAdapter<RSSItem> adapter = new ArrayAdapter<RSSItem>(this,android.R.layout.simple_list_item_1,feed.getAllItems());

        itemlist.setAdapter(adapter);

        itemlist.setOnItemClickListener(this);

        itemlist.setSelection(0);
    }

    @Override
    public void onItemClick(AdapterView parent, View v, int position, long id)
    {
        //Log.i(tag,"item clicked! [" + feed.getItem(position).getTitle() + "]");       

        Intent itemintent = new Intent(this,ShowDescription.class);

        Bundle b = new Bundle();
        b.putString("title", feed.getItem(position).getTitle());
        b.putString("description", feed.getItem(position).getDescription());
        b.putString("link", feed.getItem(position).getLink());
        b.putString("pubdate", feed.getItem(position).getPubDate());

        itemintent.putExtra("android.intent.extra.INTENT", b);

        startActivity(itemintent);
    }
}

Это мой XML:

<?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_width="fill_parent" 
android:layout_height="wrap_content" 
android:text="Android RSSReader"
android:id="@+id/feedtitle"/>
<TextView  
android:layout_width="fill_parent" 
android:layout_height="wrap_content" 
android:text=""
android:id="@+id/feedpubdate"/>
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/itemlist"

android:fastScrollEnabled="true"/>    
 </LinearLayout>

Вот что теперь выглядит в Eclipse:

ListView Currently

Это выглядит так:

In Process

Как сделать текст Sub Item отображенным pubDate, который был получен из RSS-канала?

4b9b3361

Ответ 1

Простейшим решением является замена ArrayAdapter и android.R.layout.simple_list_item_1, которые вы используете с предопределенным макетом SimpleAdapter и android.R.layout.simple_list_item_2. Этот макет состоит из двух TextView s, с идентификатором android.R.id.text1 ( "элемент" ) и android.R.id.text2 ( "подпункт" ) соответственно, который вам понадобится в качестве ссылки для SimpleAdapter to работа.

В глядя на конструктор для SimpleAdapter вы заметите, что помимо экземпляра Context и идентификатора ресурса макета, он принимает три параметра, которые могут быть для вас новыми:

  • a List<? extends Map<String, ?>>, где вы помещаете элементы, которые хотите показать ListView. Элементы имеют вид Map, то есть нечто похожее на структуру, состоящую из свойств в виде пар имя/значение. Например, вы можете использовать "title" и "date" в качестве ключей для названия и даты каждого элемента RSS, соответственно.
  • массив строк, где нужно поместить имена ключей на каждой карте, которые вы хотите показать на ListView.
  • массив целых чисел, где вам нужно поместить идентификаторы частей в представление элемента списка, где вы хотите отобразить отдельные элементы, на которые ссылаются ключи в предыдущем массиве строк. Например, если вы хотите показать заголовок и дату элемента RSS в представлениях "элемент" и "подпункт" соответственно, вы используете new String[] { "title", "date" } как массив аргументов строк, а new int[] { android.R.id.text1, android.R.id.text2 } в качестве этого аргумента.

Пример грубого кода, чтобы дать вам идею:

List<Map<String, String>> data = new ArrayList<Map<String, String>>();
for (RSSItem item : feed.getAllItems()) {
    Map<String, String> datum = new HashMap<String, String>(2);
    datum.put("title", item.getTitle());
    datum.put("date", item.getDate().toString());
    data.add(datum);
}
SimpleAdapter adapter = new SimpleAdapter(this, data,
                                          android.R.layout.simple_list_item_2,
                                          new String[] {"title", "date"},
                                          new int[] {android.R.id.text1,
                                                     android.R.id.text2});
itemList.setAdapter(adapter);

В документации указывается, что "карты содержат данные для каждой строки и должны включать все записи, указанные в параметре from", поэтому всегда должны присутствовать заголовок и дата.

Обратите внимание, что все это с головы до ног. Я на самом деле не протестировал весь код, так что вы вполне можете столкнуться с некоторой причудой или ошибкой, которую вам нужно настроить или исправить на своем пути.

Ответ 2

У вас должен быть файл item_list.xml, например:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="6dp" >

    <TextView
        android:id="@+id/page_title"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textColor="#D8000000"
        android:textSize="16sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/page_date"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/page_title"
        android:ellipsize="marquee"
        android:lines="3"
        android:marqueeRepeatLimit="marquee_forever"
        android:textColor="#D8000000"
        android:textSize="12sp" />

</RelativeLayout>

и в вашем listadapter в методе getview:

View row = convertView;
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
row = inflater.inflate(R.layout.item_list, parent, false);

TextView listTitle = (TextView) row.findViewById(R.id.page_title);
 listTitle.setText(title);

TextView date = (TextView) row.findViewById(R.id.page_date); 
date.setText( <here put your date from RSS feed>);

return row;

это должно сделать это!

Ответ 3

Поскольку вы хотите сопоставить несколько элементов данных с несколькими видами, вы не можете использовать ArrayAdapter. Вам нужно будет использовать SimpleAdapter.

Кроме того, я заметил, что вы получаете RSS-канал в основном потоке пользовательского интерфейса. Это приведет к тому, что ваше приложение будет очень невосприимчивым. Если вы не знаете, о чем я говорю, возьмите gander в статье "Безболезненная резьба" (я считаю, что она должна быть прочитана для любого андроида разработчик). Вместо этого вы должны использовать Loader. Они были спроектированы именно для вашего типа ситуации. Хотя они не были представлены до API-10, вы все равно можете использовать их на меньших уровнях API через Пакет поддержки.