关于Java:单击列表视图中的某些项目时,如何影响列表视图之外的元素?

How to affect elements outside of a listview when some items in the listview are clicked?

我的content_main.xml布局中有一个ListView。该列表视图的内容是通过listview.setAdapter(myCustomAdapter)设置的。我在content_main.xml布局中也有一个TextView。

我创建了自己的自定义适配器ArrayAdapterItem,它扩展了ArrayAdapter。在此适配器的getView()方法中,我试图访问content_main.xml中包含的TextView。我不知道该怎么做。我需要能够这样做,因为如果单击列表中的某些项目,我想用新信息更新此TextView。但是,我无法通过parent.findViewbyId(R.id.main_activity_textView)来访问此文件。此方法在运行时返回null。

我尝试使用谷歌搜索,但是只能得到与我无关的不同主题的答案。

我是android的新手。解决这个问题的方法可能很简单,但是我找不到有关此问题的任何教程或有关stackoverflow的问题。

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package com.example.simran.listviewtest;

    import android.app.AlertDialog;
    import android.os.Bundle;
    import android.support.design.widget.FloatingActionButton;
    import android.support.design.widget.Snackbar;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.Toolbar;
    import android.view.View;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.ListView;

    public class MainActivity extends AppCompatActivity {
        AlertDialog alertDialogStores;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);

            showList();

            FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Snackbar.make(view,"Replace with your own action", Snackbar.LENGTH_LONG)
                            .setAction("Action", null).show();
                }
            });
        }

        public void showList(){

            // add your items, this can be done programatically
            // your items can be from a database
            ObjectItem[] ObjectItemData = new ObjectItem[20];

            ObjectItemData[0] = new ObjectItem(91,"Mercury");
            ObjectItemData[1] = new ObjectItem(92,"Watson");
            ObjectItemData[2] = new ObjectItem(93,"Nissan");
            ObjectItemData[3] = new ObjectItem(94,"Puregold");
            ObjectItemData[4] = new ObjectItem(95,"SM");
            ObjectItemData[5] = new ObjectItem(96,"7 Eleven");
            ObjectItemData[6] = new ObjectItem(97,"Ministop");
            ObjectItemData[7] = new ObjectItem(98,"Fat Chicken");
            ObjectItemData[8] = new ObjectItem(99,"Master Siomai");
            ObjectItemData[9] = new ObjectItem(100,"Mang Inasal");
            ObjectItemData[10] = new ObjectItem(101,"Mercury 2");
            ObjectItemData[11] = new ObjectItem(102,"Watson 2");
            ObjectItemData[12] = new ObjectItem(103,"Nissan 2");
            ObjectItemData[13] = new ObjectItem(104,"Puregold 2");
            ObjectItemData[14] = new ObjectItem(105,"SM 2");
            ObjectItemData[15] = new ObjectItem(106,"7 Eleven 2");
            ObjectItemData[16] = new ObjectItem(107,"Ministop 2");
            ObjectItemData[17] = new ObjectItem(108,"Fat Chicken 2");
            ObjectItemData[18] = new ObjectItem(109,"Master Siomai 2");
            ObjectItemData[19] = new ObjectItem(110,"Mang Inasal 2");

            // our adapter instance
            ArrayAdapterItem adapter = new ArrayAdapterItem(this, R.layout.list_view_row_item, ObjectItemData);

            // create a new ListView, set the adapter and item click listener
            ListView listViewItems = (ListView)findViewById(R.id.main_activity_listView);
            listViewItems.setAdapter(adapter);
            listViewItems.setOnItemClickListener(new OnItemClickListenerListViewItem());

        }

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

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();

            //noinspection SimplifiableIfStatement
            if (id == R.id.action_settings) {
                return true;
            }

            return super.onOptionsItemSelected(item);
        }
    }

ArrayAdapterItem.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
            package com.example.simran.listviewtest;

        import android.app.Activity;
        import android.content.Context;
        import android.view.LayoutInflater;
        import android.view.View;
        import android.view.ViewGroup;
        import android.widget.ArrayAdapter;
        import android.widget.TextView;

        import org.w3c.dom.Text;

        /**
         * Created by simra on 12/23/2015.
         */

        public class ArrayAdapterItem extends ArrayAdapter<ObjectItem> {
            Context mContext;
            int layoutResourceId;
            ObjectItem data[] = null;

            public ArrayAdapterItem(Context mContext, int layoutResourceId, ObjectItem[] data) {
                super(mContext, layoutResourceId, data);

                this.layoutResourceId = layoutResourceId;
                this.mContext = mContext;
                this.data = data;
            }


            @Override
            public View getView(int position, View convertView, ViewGroup parent) {

                /*
                 * The convertView argument is essentially a"ScrapView" as described is Lucas post
                 * http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
                 * It will have a non-null value when ListView is asking you recycle the row layout.
                 * So, when convertView is not null, you should simply update its contents instead of inflating a new row layout.
                 */

                if (convertView == null) {
                    // inflate the layout
                    LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
                    convertView = inflater.inflate(layoutResourceId, parent, false);
                }

                //trying set the text of the textView in the main_activity.
                TextView mainActivityTextView = (TextView) parent.findViewById(R.id.main_activity_textView);
                mainActivityTextView.setText("some new text");

                // object item based on the position
                ObjectItem objectItem = data[position];

                // this sets the text and tag for the item in the list. Works fine
                TextView textViewItem = (TextView)   convertView.findViewById(R.id.textViewItem);
                textViewItem.setText(objectItem.itemName);
                textViewItem.setTag(objectItem.itemId);

                return convertView;

            }
        }

content_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
     `<?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingBottom="@dimen/activity_vertical_margin"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingTop="@dimen/activity_vertical_margin"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            tools:context="com.example.simran.listviewtest.MainActivity"
            tools:showIn="@layout/activity_main">

            <TextView
                android:id="@+id/hello_world"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Hello World!"
                android:layout_alignParentTop="true"/>

            <ListView
                android:id="@+id/options_list"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/hello_world">

            </ListView>

        </RelativeLayout>`

list_view_row_item.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
        <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="10dp">

        <TextView
            android:id="@+id/textViewItem"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:text="Item name here..."
            android:textSize="15dp" />
    </RelativeLayout>

ObjectItem.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    package com.example.simran.listviewtest;

/**
 * Created by simra on 12/23/2015.
 */

public class ObjectItem {
    public int itemId;
    public String itemName;

    // constructor
    public ObjectItem(int itemId, String itemName) {
        this.itemId = itemId;
        this.itemName = itemName;
    }
}


您有三个选择(仅三个示例):

  • 使用ListView随附的单击侦听器。 (首选方法)
  • 通过适配器构造函数注入依赖项。
  • 使用侦听器模式来通知活动。

注意:我不确定为什么在调用getView方法时为什么需要更新TextView,可以经常调用getView退出(例如在滚动时),这意味着TextView几乎会随机更新。我会选择选项1,这是对列表中项目的点击做出反应的最可靠,最可取的方式。

选项1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ExampleActivity extends Activity implements OnItemClickListener {

    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Set layout etc

        textView = (TextView) findViewById(some id); //Find the TextView

        ListView list = (ListView) findViewById(some id); //Find the ListView
        //Set adapter etc.
        list.setOnItemClickListener(this);
    }


    @Override
    public void onItemClick(AdapterView< ? > adapterView, View view, int pos, long id) {
        textView.setText("Some text"); //Get the text from your adapter for example
    }
}

选项2:

1
2
3
public ArrayAdapterItem(Context mContext, int layoutResourceId, ObjectItem[] data, TextView textview) {
    //etc.
}

选项3:

适配器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
    package com.example.simran.listviewtest;

    import android.app.Activity;
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.TextView;

    import org.w3c.dom.Text;

    /**
     * Created by simra on 12/23/2015.
     */

    public class ArrayAdapterItem extends ArrayAdapter<ObjectItem> {
        Context mContext;
        int layoutResourceId;
        ObjectItem data[] = null;
        ArrayAdapterItemCallback callback;

        public interface ArrayAdapterItemCallback {
            updateText(String text);
        }



        public ArrayAdapterItem(Context mContext, int layoutResourceId, ObjectItem[] data, ArrayAdapterItemCallback callback) {
            super(mContext, layoutResourceId, data);

            this.layoutResourceId = layoutResourceId;
            this.mContext = mContext;
            this.data = data;
            this.callback = callback;
        }


        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            /*
             * The convertView argument is essentially a"ScrapView" as described is Lucas post
             * http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
             * It will have a non-null value when ListView is asking you recycle the row layout.
             * So, when convertView is not null, you should simply update its contents instead of inflating a new row layout.
             */

            if (convertView == null) {
                // inflate the layout
                LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
                convertView = inflater.inflate(layoutResourceId, parent, false);
            }

            //trying set the text of the textView in the main_activity.
            callback.updateText("some new text");

            // object item based on the position
            ObjectItem objectItem = data[position];

            // this sets the text and tag for the item in the list. Works fine
            TextView textViewItem = (TextView)   convertView.findViewById(R.id.textViewItem);
            textViewItem.setText(objectItem.itemName);
            textViewItem.setTag(objectItem.itemId);

            return convertView;

        }
    }

活动:

1
2
3
4
5
6
7
8
9
10
public class ExampleActivity extends Activity implements UpdateActivity {
    //etc.

    TextView text; //Init this in the onCreate

    @Override
    void updateText(String text){
         text.setText(text);
    }
}


在Android中使用列表视图适配器时,几乎应始终使用它们将其放置在类的内部类中-在这种情况下,这是您的MainActivity类。当适配器是内部类时,它可以使用封闭类的所有属性。如果要更新的textView还不存在,则应该在该位置。


您需要的不是很困难,请尝试再想一遍您真正想要的,

您拥有的是TextView来填充实例ObjectItem类型的实例变量

中的信息

您可以轻松地从这样单击的列表中获取对象

1
2
3
4
5
6
7
8
9
10
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView< ? > parent, View view, int position, long id) {
                ObjectItem singleItem = (ObjectItem) listView.getItemAtPosition(position);
                textView.setText(""+singleItem.itemName);
                //this is the textView which you should already get the reference in Main Activity

            }

        });

当您评估需要的内容时,可以轻松地减少代码的数量,而无需实施某些您可能无法用于其他任何工作的代码。抱歉,您的评论是这样,这是使您的汽车转弯的另一种方法:)


您可以使用LocalBroadCastManager,因此您可以在应用程序内从任何地方进行交流

您可以使用此方法来检出如何使用LocalBraodcastManager。

如何使用LocalBroadcastManager?


您应该替换:

1
parent.findViewById(...) by convertView.findViewById(...)