【问题标题】:Android - Updating ListView on Dialog clickAndroid - 在对话框单击时更新 ListView
【发布时间】:2014-07-11 06:28:39
【问题描述】:

我已经尝试了一段时间了,但我的经验不足已经让我变得最好了。任何关于我应该如何处理该问题的指示或建议将不胜感激。

我有一个自定义 ListView,每个项目都包含两个字符串。 ListView 中的一个特定项目正在更改操作模式。我想要实现的是:

  1. 单击此 ListView 项目时,打开一个对话框,其中包含附加到单选按钮的列表。
  2. 选择 Dialog 项目之一后,关闭 Dialog 并更改该项目中的两个 ListView 字符串之一以反映该模式选择。

我的问题是:如何在单击对话框按钮时更新我的​​ ListView 项目?

我可以很好地创建 ListView 和 Dialog,但事实证明更新 ListView 很困难。可以设置初始值,但不会更新。我知道我需要调用 .notifyDataSetChanged,但是由于我希望在对话框的 onItemClick 中发生这种情况,我收到错误消息,类似于“无法引用在不同方法中定义的内部类中的非最终变量” ",我的变量不能是最终的。

我尝试过的:

  • 在对话框关闭前立即通知数据更改。出现“非最终变量”错误。
  • 实现模型-视图-控制器设置并尝试创建一个类似于“onVariableChangeListener”的方法,但我放弃了这个想法,因为它似乎有点离题而且我不太了解它。
  • 创建一种方法来调出 Dialog 和另一种方法来更新 ListView 数据。问题是 Update 方法没有等待 Dialog 项目被点击。即使更改并重新打开对话框选择,ListView 也不会更新。
  • 创建一个方法,其操作类似于 onCreateView,只要单击项目就会调用该方法。它应该创建并扩展一个新的 ListView。由于它是在 onItemClick 中调用的,因此它没有“非最终变量”错误,尽管它需要我创建 onCreateView 参数的最终实例。我不确定这会产生什么影响。这是一种有效的方法吗?

下面的代码是后两种想法的混合。 Dialog和update分别有方法,虽然update不等待dialog,进入update方法的参数是final的。

我希望解决方案简单明了,但我相信存在多个错误。我知道 SO 喜欢提出可以适用于稍后可能会阅读本文的其他人的问题,所以如果这对我的情况有点特殊,我深表歉意。任何帮助表示赞赏!

CalibrationFragment.java

public class CalibrationFragment extends Fragment{
    private Context mContext;
    private ArrayList<DataItem> data = new ArrayList<DataItem>(); // DataItem is a class that sets two strings
    private ArrayList<DataItem> currentData = new ArrayList<DataItem>(); // Two records kept to identify changes
    ListView myList;
    int checkedItem1 = 0; // For the dialog boxes.

    @Override
    public void onCreate (Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        mContext = getActivity(); // Get the context of the Activity and therefore the fragment
        myList = new ListView (mContext); // Create a ListView

        // Set initial values
        calibrationData readData = new calibrationData(); // readData will contain all ListView values
        // ... other items...
        readData.setMode(checkedItem1, mContext); // Set to 0, 1 or 2 indicating different modes
        // ... other items...

        // Create elements to be added to the list
        // ...
        DataItem calibration4 = new DataItem(getResources().getString(R.string.mode_calibration), readData.getMode());
        // readData.getMode() returns different strings depending on int input
        // ...

        // Add elements to the list
        // ...
        data.add(calibration4);
        // ...

        currentData = data; // Initialise both as the same
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        // Inflate the view
        View rootView = inflater.inflate(R.layout.fragment_list, container, false);
        myList=(ListView) rootView.findViewById(android.R.id.list);
        // Create and set the customised adapter to take data (ArrayList<DataItem>) and format
        // each element as defined in list_row.xml
        CustomAdapter adapter = new CustomAdapter(mContext, R.layout.list_row, data);
        myList.setAdapter(adapter);
        // The above adapter is the one I need to notify            

        // For the sake of letting my code compile in onItemClick. Unsure if this causes further issues.
        final LayoutInflater finalInflater = inflater;
        final ViewGroup finalContainer = container;
        final Bundle finalSavedInstanceState = savedInstanceState;

        // CustomAdapter adapter cannot be used in setOnItemClickListener because it is non-final
        myList.setOnItemClickListener(new AdapterView.OnItemClickListener()
        {
            public void onItemClick(AdapterView<?> parentAdapter, View view, int position, long id)
            {
                switch((int)id){
                // [Different cases here]

                case 3: // Clicks of Mode item
                    // Creates Dialog
                    showDialog((int)id, checkedItem1);
                    // updateData executes as Dialog is generated, not clicked or closed. Do not want this.
                    updateData(finalInflater, finalContainer, finalSavedInstanceState);
                break;

                // [Rest of the cases and default statement here]
                }
            }
        });

        return rootView; // onCreateView must return a View variable if displaying a UI.
    }

    public void showDialog(int id, int checkedItem)
    {
        // In case I want to have other dialogs later, ensure this is for Mode selection.
        if(id == 3){
            final CharSequence[] modeItems = {
                    "Mode 1", "Mode 2", "Mode 3"
            }; // For Dialog
            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            builder.setTitle(getResources().getString(R.string.mode_calibration));
            builder.setSingleChoiceItems(modeItems, checkedItem, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int item) {
                    checkedItem1 = item; // Change checkedItem1 to the index selected in the dialog
                    calibrationData readData = new calibrationData();
                    readData.setMode(checkedItem1, mContext); // Set Mode depending on checkedItem
                     // Create DataItem representing new mode
                    DataItem newMode = new DataItem(getResources().getString(R.string.mode_calibration), readData.getMode());
                    currentData.set(3, newMode); // Set new mode into currentData.
                    // Eventual comparison with var 'data' will indicate a change

                    dialog.dismiss();                       
                }
            });
            AlertDialog alert = builder.create();
            alert.show();   
        }

        public View updateData(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){

            // Inflate the new view
            View rootView = inflater.inflate(R.layout.fragment_list, container, false);
            myList=(ListView) rootView.findViewById(android.R.id.list);
            // Create and set the customised adapter to take data (ArrayList<DataItem>) and format
            // each element as defined in list_row.xml
            CustomAdapter adapter = new CustomAdapter(mContext, R.layout.list_row, data);
            myList.setAdapter(adapter);

            // As this is only called in onClick, I can work with data assuming something has changed and been clicked.
            int i = 0;
            // Compare each element inside data and currentData.
            for(i = 0; i < data.size(); i++){
                if(data.get(i) != currentData.get(i)) data = currentData;
                if(i==5) Toast.makeText(mContext, "Iterating to end", Toast.LENGTH_SHORT).show(); // debug purposes
            }
            adapter.notifyDataSetChanged(); // Update list

            return rootView;
        }

【问题讨论】:

    标签: android listview dialog fragment onitemclicklistener


    【解决方案1】:

    我建议您创建一个单独的DialogFragment 来显示 modeItems 并将所选项目传递给您的 CalibrationFragment。

    首先,阅读http://developer.android.com/training/basics/fragments/communicating.html

    创建一个 DialogFragment 并在其中编写一个带有回调方法的侦听器,以通知对话框中的选定项。然后,在您的 CalibrationFragment 和回调中实现此侦听器,在列表数据上设置项目并更新列表适配器。

    【讨论】:

    • 我将不得不阅读回调方法,但只是为了验证我是否理解该过程,您是说我应该 (1) 编写一个片段,它是我的 CalibrationFragment 的子片段。 java,(2)当我点击一个ListItem时,打开DialogFragment,它也会打开我的Dialog,(3)当一个Dialog项目被点击时,使用回调方法将信息反馈给CalibrationFragment并在那里进行更改?
    • (1) 您将编写的 DialogFragment 不应是 CalibrationFragment 的子代。它本身必须是一个 DialogFragment。 (2) 是的,请阅读 DialogFragment 文档。 (3) 正确。
    【解决方案2】:

    你必须删除

    updateData(finalInflater, finalContainer, finalSavedInstanceState);

    来自 onitemclick 的行

    并添加到 showdialog() 在点击事件中

    可能会工作

    【讨论】:

    • 你的意思是从 showDialog 的 onClick 事件中调用 updateData 吗?不走运,尽管它确实强制代码等到对话框内的某些内容被选中,这解决了该部分。然而,ListView 仍然没有更新。
    【解决方案3】:

    您只需在对话框确定按钮的单击事件上使用适当的选定值更新ArrayList&lt;DataItem&gt; dataarrayList。之后立即在同一个点击事件(对话框确定按钮)中通知您的ListView,如myList.notifyDataSetChanged(); 生成对话框的活动。希望对你有帮助……

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-20
      • 2016-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多