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 |
您有三个选择(仅三个示例):
- 使用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还不存在,则应该在该位置。
您需要的不是很困难,请尝试再想一遍您真正想要的,
您拥有的是
中的信息
您可以轻松地从这样单击的列表中获取对象
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(...) |