Java Android ListView-在活动开始时添加HTML链接

Java Android ListView-在活动开始时添加HTML链接,java,android,html,listview,Java,Android,Html,Listview,我有一个活动,它显示html链接的列表视图,每个链接都存储在TextView中,用户可以通过指定名称和web地址来添加和删除链接。每个链接都以HTML格式存储在listview中,如下所示,用户将单击“google”启动web浏览器 我已经尝试了几种方法来实现这一点,包括XML文件中的android:autolink=web,下面的方法是唯一有效的方法。但是,我无法调用它,因为活动正在从onCreate或onStart初始化,因为getChildAt方法返回null TextView want

我有一个活动,它显示html链接的列表视图,每个链接都存储在TextView中,用户可以通过指定名称和web地址来添加和删除链接。每个链接都以HTML格式存储在listview中,如下所示,用户将单击“google”启动web浏览器

我已经尝试了几种方法来实现这一点,包括XML文件中的android:autolink=web,下面的方法是唯一有效的方法。但是,我无法调用它,因为活动正在从onCreate或onStart初始化,因为getChildAt方法返回null

 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);
     }
}

让您创建扩展ArrayAdapter的类,然后重写getView。。。方法在那里,您必须有一个layoutiner和一个引用一行的视图,该行仅命名为row。这是执行row.setOnClickListenernew View.OnClickListener{/*…*/}的最佳位置。如果您将同时显示大量数据,请不要忘记创建一个支架


有关自定义ArrayAdapter的更多信息,例如

解决方案是从ArrayAdapter获取文本视图,而不是从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中使用此代码,它应该可以工作

对于未来的观众,这里有一个问题的解决方案,并简要说明我是如何发现它的

我尝试了舒尔茨博士的解决方案,但没有发现任何变化。他评论说,使用带有字符串资源的textview是可行的。我尝试了这一点,并意识到listview需要跨对象传递

我找到了一个创建跨越式Listview的解决方案,然后添加了一个onItemClickListener,它在提供的Textview对象上调用setMovementMethod

我意识到之前的解决方案不起作用,因为适配器的“getview”方法没有提供对listview对象的引用,而是提供了一个与我认为的相同数据的副本。重写onItemClick方法是获取对list对象的引用的一种快速解决方案,它允许您直接操作它并对其执行任何操作

我在下面添加了用于测试此解决方案的代码。它创建两个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();
            }

        }
    });

}

你把TextView的东西叫到哪里去了?它不在您发布的代码中。来自一个名为makeLinksVisible的方法。最初我在setAdapteradapter之后调用它,但是textview每次都返回null。当我添加一个按钮并从那里调用makeLinksVisible时,它成功了。我已将其添加到主要评论中。请参见下面我的答案。解决方案是从ArrayAdapter而不是ListView获取TextView。这不起作用。不幸的是,该视图确实返回了相应的TextView,但当活动实际显示链接尚未创建时,它仍然只是将类似这样的内容显示为文本Google,这是因为您没有正确格式化字符串。您使用的是单引号,而不是双引号。它应该是这样的:这是注释,没有格式化它,不确定为什么-在我的代码中,文本与您的完全相同。我刚刚在一个活动中尝试了这一点。我创建了一个TextView,并使用了一个字符串资源来显示如下文本:然后在我的onCreate方法中,我放置了以下内容:TextView TextView=TextView findViewByIdR.id.clickableLink;textView.setMovementMethodLinkMovementMethod.getInstance;一切都很好,当我点击浏览器启动的链接并转到google.com.Cheers这里寻求帮助时,之所以有效是因为字符串资源被转换成了一个跨对象。我已经想出了一个解决方案,我将发布它来回答主要问题,并解释为什么它以前不起作用。