我有一个活动,显示html链接的列表视图,每个链接都存储在TextView中,用户可以通过指定名称和网址来添加和删除链接。每个链接都以HTML格式存储在listview中,如下所示,用户可以点击“google”一词来启动网络浏览器。
<a href='http://www.google.com'>google</a>
我已经尝试了几种方法来使链接执行此操作,包括XML文件中的android:autolink="web"
,以下方法是唯一有效的方法。但是,由于getChildAt方法返回null,因此我无法调用它,因为活动正在初始化(来自onCreate()或onStart())。
TextView wantedView = (TextView) listView.getChildAt(i);
wantedView.setText(Html.fromHtml(s));
wantedView.setClickable(true);
wantedView.setMovementMethod(LinkMovementMethod.getInstance());
但是,如果我设置了一个可调用此代码的可点击按钮,那么它可以正常工作,尽管向列表添加新链接会恢复格式化。
有人知道为什么我在初始化时无法访问TextView对象,还有其他方法可以做到这一点?我在下面发布了我的布局文件和listview启动代码。
simplerow.xml <TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rowTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="15sp"
android:visibility="visible"
android:autoLink=""
android:gravity="center">
listview.xml <ListView
android:id="@+id/listView1"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test2);
listView1 = (ListView) findViewById(R.id.listView1);
items = new String[]{ "<a href='http://www.facebook.com'>facebook</a>",
"<a href='http://www.google.com'>google</a>",
"<a href='http://www.twitter.com'>twitter</a>" };
list = new ArrayList<>();
for(int i=0; i<items.length; i++) {
list.add(items[i]);
}
adapter = new ArrayAdapter<String>(Test.this, R.layout.simplerow, list);
listView1.setAdapter(adapter);
makeLinksVisible();
}
private void makeLinksVisible() {
int i = 0;
TextView wantedView = (TextView) listView.getChildAt(i);
while (wantedView != null) {
String s = wantedView.getText().toString();
wantedView.setText(Html.fromHtml(s));
wantedView.setClickable(true);
wantedView.setMovementMethod(LinkMovementMethod.getInstance());
i++;
wantedView = (TextView) listView.getChildAt(i);
}
}
答案 0 :(得分:0)
让您创建扩展ArrayAdapter<String>
的类,然后覆盖getView(...)
方法。在那里你必须有一个LayoutInflatter和一个引用单行的视图(简称为row
)。这是执行row.setOnClickListener(new View.OnClickListener() {/*...*/}
的最佳位置。如果您有大量的数据显示,请不要忘记创建一个持有者。
有关自定义ArrayAdapters的更多信息,例如here
答案 1 :(得分:0)
解决方案是从ArrayAdapter获取TextView,而不是ListView。因此,如果您使用的是ListActivity,则可以执行以下操作:
ListView listView = getListView();
ArrayAdapter arrayAdapter = listView.getAdapter();
FrameLayout frameLayout = (FrameLayout) arrayAdapter.getView(0, null, null);
TextView wantedView = (TextView) frameLayout.findViewById(R.id.your_text_view);
wantedView.setText(Html.fromHtml(s));
wantedView.setClickable(true);
wantedView.setMovementMethod(LinkMovementMethod.getInstance());
这段代码当然假设使用了FrameLayout,但您只需将其替换为您尝试访问的TextView的任何父容器。然后在getView()
方法中,您将传入TextView的位置(我仅使用零作为示例)。但是,如果您尝试在onCreate()
中使用此代码,它应该可以正常运行。
答案 2 :(得分:0)
对于任何未来的观众,这里是问题的解决方案,以及我如何找到它的简要说明。
我尝试了drschultz解决方案并注意到没有变化。他评论说,使用带有字符串资源的textview可以正常工作。我尝试了这一点,并意识到需要传递列表视图跨越对象。
我找到了创建Spanned Listview的解决方案 - here - 然后添加了一个onItemClickListener,它在提供的Textview对象上调用了setMovementMethod。
我意识到之前的解决方案不起作用,因为适配器的getview&#39;方法没有提供对listview对象的引用,而是提供了具有相同数据的副本(我认为)。覆盖onItemClick方法是获取对列表对象的引用的快速解决方案,它允许您直接操作它并执行任何您喜欢的操作。
我已添加了以下用于测试此解决方案的代码。它创建了两个html引用的列表。第一次单击textview会调用onItemClick方法,然后再单击一次会将您带到指定的网页。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
String s = new String("<a href=\"http://www.facebook.com\">facebook</a>");
Spanned sp = Html.fromHtml(s);
String s1 = new String("<a href=\"http://www.google.com\">google</a>");
Spanned sp1 = Html.fromHtml(s1);
listValues = new ArrayList<>();
listValues.add(sp);
listValues.add(sp1);
setListAdapter(new SpannedAdapter(this, listValues));
ListView l = getListView();
l.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
try {
LinearLayout linearLayout = (LinearLayout) view;
TextView wantedView = (TextView) linearLayout.findViewById(R.id.rowTextView);
wantedView.setClickable(true);
wantedView.setMovementMethod(LinkMovementMethod.getInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
});
}