#java #android #listview #android-layout
#java #Android #listview #android-макет
Вопрос:
Я создал программу чтения RSS, в которой перечислены элементы в listview. Мне также нужна дата под каждым элементом, но я понятия не имею, как это сделать. Мне нужна чья-то помощь, чтобы в тексте подпункта отображалась дата публикации, полученная из 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:
Вот как это выглядит при запуске:
Как заставить текст подпункта отображать дату публикации, полученную из RSS-канала?
Ответ №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
работы.
<a rel=»noreferrer noopener nofollow» href=»https:///developer.android.com/reference/android/widget/SimpleAdapter.html#SimpleAdapter(android.content.Context, java.util.List<? extends java.util.Map>, int, java.lang.String[], int[])» rel=»noreferrer»>Взглянув на конструктор for SimpleAdapter
, вы заметите, что, помимо Context
экземпляра и идентификатора ресурса макета, он принимает три параметра, которые могут быть новыми для вас:
List<? extends Map<String, ?>>
экземпляр, в который вы помещаете элементы, которые хотитеListView
отобразить. Элементы имеют форму aMap
, то есть что-то похожее на структуру, состоящую из свойств в виде пар имя / значение. Например, вы можете использовать"title"
и"date"
как ключи для заголовка и даты каждого элемента RSS соответственно.- массив строк, куда помещаются имена ключей в каждой карте, которые вы хотите отобразить на
ListView
. - массив целых чисел, в который вам нужно поместить идентификаторы частей в представлении элемента списка, где вы хотите, чтобы отображались отдельные элементы, на которые ссылаются ключи в предыдущем массиве строк. Например, если вы хотите отобразить заголовок и дату элемента RSS в представлениях «элемент» и «подпункт» соответственно, вы используете
new String[] { "title", "date" }
в качестве аргумента array of strings иnew int[] { android.R.id.text1, android.R.id.text2 }
в качестве аргумента this .
Пример приблизительного кода, просто чтобы дать вам представление:
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;
это должно сделать это!
Комментарии:
1. Это здорово, но параметр layout_below не работает в LinearLayout. Любое решение для этого?
2. Я знаю, что это далеко не поздно, но используйте
android:orientation="vertical"
в RelativeLayout amp; removeandroid:layout_below
Ответ №3:
Поскольку вы хотите сопоставить несколько элементов данных с несколькими представлениями, вы не можете использовать ArrayAdapter. Вместо этого вам придется использовать SimpleAdapter.
Кроме того, я заметил, что вы получаете RSS-канал в основном потоке пользовательского интерфейса. Это приведет к тому, что ваше приложение будет сильно не реагировать. Если вы не знаете, о чем я говорю, взгляните на статью Безболезненная потоковая обработка (я считаю ее обязательной для прочтения любым разработчиком Android). Вместо этого вам следует использовать загрузчик. Они были разработаны именно для вашего типа ситуации. Хотя они не были представлены до API-10, вы все равно можете использовать их на меньших уровнях API через пакет поддержки.
Комментарии:
1. Я поддерживаю предложение о переносе загрузки канала из потока пользовательского интерфейса. Просто хочу добавить, что другим способом сделать это, если OP не хочет нести бремя пакета поддержки, может быть использование
AsyncTask
.2. Не бойтесь пакета поддержки! Это действительно просто в использовании, совсем не обременительно 🙂
3. Где я могу получить эту статью
Ответ №4:
создайте пользовательский ListView http://saigeethamn.blogspot.com/2010/04/custom-listview-android-developer.html