如何从 Android 中的 Activity 访问自定义适配器内片段的 UI 元素
How can I access UI Elements of a fragment inside of a Custom Adapter From an Activity in Android
大家好,我正在开发一个应用程序,其中有多个活动(活动 A、B、B)会膨胀此片段 (TheListFragment)。
这是它的外观的直观表示:
目前,我可以从片段本身更改描述、图像等,但这不是我想做的。我的目标是让各自的活动都能够更改片段并将片段用作可重用的列表视图。这是我的一些代码:
public class TheListFragment extends Fragment {
CustomAdapter.Holder holder;
//The listview
ListView listView;
//When the view is created
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Inflate the add new game layout view
View view = inflater.inflate(R.layout.list_view_holder, container, false);
//Setup the listview and reference it to the listview id
listView = (ListView) view.findViewById(R.id.data_list_view);
//Set the custom adapter to the listview
listView.setAdapter(new CustomAdapter(context);
return view;
}
//This custom adapter is used to fill the respective data into the listview
class CustomAdapter extends BaseAdapter {
Context context;
public CustomAdapter(Context context)) {
this.context = context;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return all_passed_data.size();
//List of data. removed it for space purposes
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
//Holds the respective fields
public class Holder {
//UI Components
TextView textview;
ImageView imageView;
LinearLayout linearLayout;
}
//Custom view
public View getView(final int position, View convertView, ViewGroup parent) {
//A holder object to reference the textviews and imageviews
holder = new Holder();
View rowView;
rowView = inflater.inflate(R.layout.custom_list_view, null);
holder.imageView = (ImageView) rowView.findViewById(R.id.custom_list_view_image);
holder.textview = (TextView) rowView.findViewById(R.id.custom_list_view_game_name);
holder.linearLayout = (LinearLayout) rowView.findViewById(R.id.left_layout);
return rowView;
}
}
}
我正在尝试从膨胀片段本身的 activity 中设置/更改 listView 内容(持有者 class 项目)。 IE,大致如下:
public class ActivityA extends Activity{
FragmentManager manager;
ListFragment fragment;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_fragment_holder);
manager = getFragmentManager();
ListFragment fragment = (ListFragment) manager.findFragmentById(R.id.the_list_fragment);
//These will not work at the moment, they read as null pointers
//This will be changed dynamically depending on the activity. Could be checkbox, imageview, etc.
fragment.holder.linearLayout.addView(holder.checkBox);
fragment.holder.textview.setText("I Want to set the text here");
//Make it do something when clicked
fragment.holder.textview.setOnClickListener(this);
//Use third party library picasso to set the image
fragment.Picasso.with(context).load("http://www.google.com/somepicture").into(holder.imageview);
}
}
但是我没有运气弄清楚如何完成这个。我已阅读这些链接:Call fragment events from activity , Android: Reusing same View object in different Activities (the case is about ad banners) , How to access UI elements created by a List Adapter from an Activity?。我是否需要实现一个以某种方式访问数据的接口?如果是这样,如何?或者我缺少其他一些方法?
所以这是我认为的完整答案。
首先让每个class各司其职。所以 Activity 有碎片,碎片有适配器,适配器有支架。
使用您需要的方法创建抽象片段,然后通过扩展抽象片段来创建该片段的具体版本。
抽象片段中的方法之一应该是 public void doSomething();.
在片段的具体版本 (A B o C) 中,实现了您在 doSomething() 方法上执行的实际 "something" 方法。在这些片段中使用某种集合来保存所需的信息(我使用数组列表)。这是列表中的实际数据,holder 将根据需要显示在屏幕上。在您的情况下,以免假设这将是要放入屏幕元素中的文本。这实际上应该是一个 class 代表屏幕上的元素,即 class GameItem 包含所有需要显示的元素,甚至是复选框状态。代表一个游戏。
然后在你的适配器(自定义适配器)中,你必须从持有的 activity.同样在此适配器中创建一个名为 public void changeGameInfo(); 的 public 方法;在方法中是您更改接收到的数组内容的地方。当您填充列表并抓取适当的值以显示在屏幕上时,持有者将访问该元素。
在您的 class 中创建片段的实例。在正确的时间调用您在片段中创建的方法 i.e.fregment.doSomething();在 doSomething 中你调用 adapter.changeGameInfo(); Since 是包含适配器实例的片段。由于适配器引用了您作为参数传递的游戏数组列表,我将知道需要显示的元素,仅此而已,
作为简历
Class XXXX 调用了 fragment.doSomething()。
在 fragment.doSoemthing 你调用 adapter.changeGameInfo()
在适配器中,您更改了作为参数的 arraylist paseed 的所需游戏表示。
viewholder 仅显示元素,在更改数组列表中的元素后,请记住调用 notifyDataSetChanged();在适配器中,以便屏幕上的实际值自动更新
查看取景器模式示例
public class InteractiveArrayAdapter extends ArrayAdapter<Model> {
private final List<Model> list;
private final Activity context;
public InteractiveArrayAdapter(Activity context, List<Model> list) {
super(context, R.layout.rowbuttonlayout, list);
this.context = context;
this.list = list;
}
static class ViewHolder {
protected TextView text;
protected CheckBox checkbox;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.rowbuttonlayout, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.label);
viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
viewHolder.checkbox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Model element = (Model) viewHolder.checkbox
.getTag();
element.setSelected(buttonView.isChecked());
}
});
view.setTag(viewHolder);
viewHolder.checkbox.setTag(list.get(position));
} else {
view = convertView;
((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
holder.checkbox.setChecked(list.get(position).isSelected());
return view;
}
}
大家好,我正在开发一个应用程序,其中有多个活动(活动 A、B、B)会膨胀此片段 (TheListFragment)。
这是它的外观的直观表示:
目前,我可以从片段本身更改描述、图像等,但这不是我想做的。我的目标是让各自的活动都能够更改片段并将片段用作可重用的列表视图。这是我的一些代码:
public class TheListFragment extends Fragment {
CustomAdapter.Holder holder;
//The listview
ListView listView;
//When the view is created
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Inflate the add new game layout view
View view = inflater.inflate(R.layout.list_view_holder, container, false);
//Setup the listview and reference it to the listview id
listView = (ListView) view.findViewById(R.id.data_list_view);
//Set the custom adapter to the listview
listView.setAdapter(new CustomAdapter(context);
return view;
}
//This custom adapter is used to fill the respective data into the listview
class CustomAdapter extends BaseAdapter {
Context context;
public CustomAdapter(Context context)) {
this.context = context;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return all_passed_data.size();
//List of data. removed it for space purposes
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
//Holds the respective fields
public class Holder {
//UI Components
TextView textview;
ImageView imageView;
LinearLayout linearLayout;
}
//Custom view
public View getView(final int position, View convertView, ViewGroup parent) {
//A holder object to reference the textviews and imageviews
holder = new Holder();
View rowView;
rowView = inflater.inflate(R.layout.custom_list_view, null);
holder.imageView = (ImageView) rowView.findViewById(R.id.custom_list_view_image);
holder.textview = (TextView) rowView.findViewById(R.id.custom_list_view_game_name);
holder.linearLayout = (LinearLayout) rowView.findViewById(R.id.left_layout);
return rowView;
}
}
}
我正在尝试从膨胀片段本身的 activity 中设置/更改 listView 内容(持有者 class 项目)。 IE,大致如下:
public class ActivityA extends Activity{
FragmentManager manager;
ListFragment fragment;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_fragment_holder);
manager = getFragmentManager();
ListFragment fragment = (ListFragment) manager.findFragmentById(R.id.the_list_fragment);
//These will not work at the moment, they read as null pointers
//This will be changed dynamically depending on the activity. Could be checkbox, imageview, etc.
fragment.holder.linearLayout.addView(holder.checkBox);
fragment.holder.textview.setText("I Want to set the text here");
//Make it do something when clicked
fragment.holder.textview.setOnClickListener(this);
//Use third party library picasso to set the image
fragment.Picasso.with(context).load("http://www.google.com/somepicture").into(holder.imageview);
}
}
但是我没有运气弄清楚如何完成这个。我已阅读这些链接:Call fragment events from activity , Android: Reusing same View object in different Activities (the case is about ad banners) , How to access UI elements created by a List Adapter from an Activity?。我是否需要实现一个以某种方式访问数据的接口?如果是这样,如何?或者我缺少其他一些方法?
所以这是我认为的完整答案。
首先让每个class各司其职。所以 Activity 有碎片,碎片有适配器,适配器有支架。
使用您需要的方法创建抽象片段,然后通过扩展抽象片段来创建该片段的具体版本。
抽象片段中的方法之一应该是 public void doSomething();.
在片段的具体版本 (A B o C) 中,实现了您在 doSomething() 方法上执行的实际 "something" 方法。在这些片段中使用某种集合来保存所需的信息(我使用数组列表)。这是列表中的实际数据,holder 将根据需要显示在屏幕上。在您的情况下,以免假设这将是要放入屏幕元素中的文本。这实际上应该是一个 class 代表屏幕上的元素,即 class GameItem 包含所有需要显示的元素,甚至是复选框状态。代表一个游戏。
然后在你的适配器(自定义适配器)中,你必须从持有的 activity.同样在此适配器中创建一个名为 public void changeGameInfo(); 的 public 方法;在方法中是您更改接收到的数组内容的地方。当您填充列表并抓取适当的值以显示在屏幕上时,持有者将访问该元素。
在您的 class 中创建片段的实例。在正确的时间调用您在片段中创建的方法 i.e.fregment.doSomething();在 doSomething 中你调用 adapter.changeGameInfo(); Since 是包含适配器实例的片段。由于适配器引用了您作为参数传递的游戏数组列表,我将知道需要显示的元素,仅此而已,
作为简历 Class XXXX 调用了 fragment.doSomething()。 在 fragment.doSoemthing 你调用 adapter.changeGameInfo() 在适配器中,您更改了作为参数的 arraylist paseed 的所需游戏表示。 viewholder 仅显示元素,在更改数组列表中的元素后,请记住调用 notifyDataSetChanged();在适配器中,以便屏幕上的实际值自动更新
查看取景器模式示例
public class InteractiveArrayAdapter extends ArrayAdapter<Model> {
private final List<Model> list;
private final Activity context;
public InteractiveArrayAdapter(Activity context, List<Model> list) {
super(context, R.layout.rowbuttonlayout, list);
this.context = context;
this.list = list;
}
static class ViewHolder {
protected TextView text;
protected CheckBox checkbox;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.rowbuttonlayout, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.label);
viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
viewHolder.checkbox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Model element = (Model) viewHolder.checkbox
.getTag();
element.setSelected(buttonView.isChecked());
}
});
view.setTag(viewHolder);
viewHolder.checkbox.setTag(list.get(position));
} else {
view = convertView;
((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
holder.checkbox.setChecked(list.get(position).isSelected());
return view;
}
}