单击操作栏项目复选框时,更改其状态

Posted

技术标签:

【中文标题】单击操作栏项目复选框时,更改其状态【英文标题】:When clicking on action bar item checkbox change it state 【发布时间】:2015-02-16 01:18:52 【问题描述】:

我一直在实现一个应用程序,我在其中使用包含三个项目(图像视图、文本视图和复选框)的列表视图,列表视图工作正常(向下滚动时除外,它不会保持视图的状态)但我的问题为什么当我触摸操作栏的图标时,它会完全改变复选框的状态?

这是我的应用程序的正常行为:

当我点击一个复选框时,它会将状态更改为选中

但是当我按下工具栏的操作按钮时,会发生这种情况:

如果你没有点击任何动作,点击其他地方隐藏动作菜单,复选框的状态变为正常状态

我不知道为什么会发生这种情况,但我认为它必须与片段的生命周期有关

你能帮帮我吗?

这是这个片段的代码:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) 

        establecimientosList = new ArrayList<HashMap<String, String>>();
        rootView = inflater.inflate(R.layout.fragment_establecimientos,
                container, false);

        mDrawerToggle = new ActionBarDrawerToggle(getActivity(), null, 0, 0);

        return rootView;
    

    @Override
    public void onActivityCreated(Bundle savedInstanceState) 
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);
        // ListView lv = getListView();

        if (savedInstanceState == null) 
            new GetEstablecimientos().execute();
        

        ListView lv = getListView();
        lv.setOnItemClickListener(new OnItemClickListener() 

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) 
                // TODO Auto-generated method stub
                Fragment fragment = null;
                fragment = new MostrarEstablecimientoFragment();

                // mDrawerToggle.setDrawerIndicatorEnabled(false);
                Bundle bundle = new Bundle();
                bundle.putSerializable("HashMap",
                        establecimientosList.get(arg2));
                bundle.putInt(ID, arg2);
                fragment.setArguments(bundle);

                android.app.FragmentManager fragmentManager = getFragmentManager();
                fragmentManager.beginTransaction()
                        .replace(R.id.content_frame, fragment)
                        .addToBackStack(null).commit();
                ((ActionBarActivity) getActivity()).getSupportActionBar()
                        .setTitle(
                                establecimientosList.get(arg2).get(TAG_NOMBRE));

            
        );
    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        // TODO Auto-generated method stub;
        mDrawerToggle.setDrawerIndicatorEnabled(true);
        return super.onOptionsItemSelected(item);
    

我在这个片段中有一个用于从 Internet 检索 ListView 数据的 Asystask

        @Override
        protected void onPostExecute(Void result) 
            super.onPostExecute(result);
            // Dismiss the progress dialog
            if (pDialog.isShowing())
                pDialog.dismiss();
            /**
             * Updating parsed JSON data into ListView
             * */
            if (!establecimientosList.isEmpty()) 
                LazyAdapter mAdapter = new LazyAdapter(getActivity(),
                        establecimientosList, "RobotoTTF/Roboto-Thin.ttf");
                setListAdapter(mAdapter);
             else 
                TextView textoError = (TextView) rootView
                        .findViewById(R.id.textViewEstablecimientoError);
                textoError.setVisibility(View.VISIBLE);
                ListView lv = getListView();
                lv.setVisibility(View.GONE);
                Toast.makeText(getActivity(), "Error", Toast.LENGTH_LONG)
                        .show();
            
        

这是适配器的代码:

  public class LazyAdapter extends BaseAdapter 

    private Activity activity;
    private ArrayList<HashMap<String, String>> data;
    private static LayoutInflater inflater = null;
    public ImageLoader imageLoader;
    private Typeface tf;

    private final ArrayList<Establecimiento> listEstab;

    private SharedPreferences sharedP;

    public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d,
            String font, ArrayList<Establecimiento> posEstablecimiento) 
        activity = a;
        data = d;
        inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader = new ImageLoader(activity.getApplicationContext());
        tf = Typeface.createFromAsset(a.getAssets(), font);
        sharedP = a.getSharedPreferences(PREFENCIAS_FAVORITOS,
                Context.MODE_PRIVATE);
        listEstab = posEstablecimiento;
    

    public int getCount() 
        return data.size();
    

    public Object getItem(int position) 
        return position;
    

    public long getItemId(int position) 
        return position;
    

    public View getView(int position, View convertView, ViewGroup parent) 
        View vi = convertView;
        final int pos = position;
        if (convertView == null) // 
            vi = inflater.inflate(R.layout.list_item, null);

        TextView nombre = (TextView) vi
                .findViewById(R.id.nombreEstablecimientoList);
        TextView descripcion = (TextView) vi.findViewById(R.id.descripcionList);
        TextView localidad = (TextView) vi.findViewById(R.id.localidadList);
        // thumb image
        ImageView thumb_image = (ImageView) vi.findViewById(R.id.list_image);
        CheckBox checkFav = (CheckBox) vi.findViewById(R.id.imageList);

        HashMap<String, String> establecimiento = new HashMap<String, String>();
        establecimiento = data.get(position);

        // Setting all values in listview
        nombre.setText(establecimiento.get(TAG_NOMBRE));
        descripcion.setText(establecimiento.get(TAG_DESCRIPCION));
        localidad.setText(establecimiento.get(TAG_LOCALIDAD));
        imageLoader.DisplayImage(establecimiento.get(TAG_IMAGEN_TIPO),
                thumb_image);
        checkFav.setChecked(listEstab.get(position).getFavorito());
        checkFav.setOnClickListener(new View.OnClickListener() 

            @Override
            public void onClick(View arg0) 
                // TODO Auto-generated method stub
                // Actualizo lo que vale en las variables de entorno
                sharedP.edit()
                        .putBoolean(
                                String.valueOf(listEstab.get(pos).getId()),
                                !sharedP.getBoolean(String.valueOf(listEstab
                                        .get(pos).getId()), false)).commit();

                listEstab.get(pos).setFavorito(
                        !listEstab.get(pos).getFavorito());
                Toast.makeText(activity,
                        String.valueOf(listEstab.get(pos).getFavorito()),
                        Toast.LENGTH_SHORT).show();
            
        );
        checkFav.setFocusable(false);

        return vi;

    

但实际上我认为问题根本不在于适配器,因为当您单击列表视图中的一个项目时,它会打开另一个带有详细列表的片段(该片段只包含文本视图和一个复选框)。这是问题的截图:

这是我点击设置菜单时发生的事情

奇怪的是,如果你点击抽屉的汉堡图标,复选框就会处于正常状态(没有任何变化)

这是最后一张截图的片段:

public class MostrarEstablecimientoFragment extends Fragment 

    SharedPreferences editor;

    HashMap<String, String> establecimiento = new HashMap<String, String>();

    CheckBox favButton;

    public MostrarEstablecimientoFragment() 
    

    @Override
    public void onCreate(Bundle savedInstanceState) 
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        setHasOptionsMenu(true);
        // ((ActionBarActivity) getActivity()).getSupportActionBar()
        // .setDisplayHomeAsUpEnabled(true);
        editor = getActivity().getSharedPreferences(PREFENCIAS_FAVORITOS,
                Context.MODE_PRIVATE);
    

    @SuppressWarnings("unchecked")
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) 

        View rootView = inflater.inflate(
                R.layout.fragment_mostrar_establecimiento, container, false);

        getActivity().setTitle("Mostrar información");

        favButton = (CheckBox) rootView.findViewById(R.id.favorite_button);

        if (getArguments() != null) 

            establecimiento = (HashMap<String, String>) getArguments()
                    .getSerializable("HashMap");

            Boolean isFav = editor.getBoolean(establecimiento.get(TAG_ID),
                    false);

            if (isFav) 
                if (favButton.isChecked() == false)
                    favButton.setChecked(true);
            

            TextView tvTitle = (TextView) rootView
                    .findViewById(R.id.nameEstablecimiento);
            tvTitle.setText(establecimiento.get(TAG_NOMBRE));
            TextView tvHorario = (TextView) rootView
                    .findViewById(R.id.textViewHorario);
            tvHorario.setText(establecimiento.get(TAG_HORARIO));
            TextView tvDescp = (TextView) rootView
                    .findViewById(R.id.textViewDescp);
            tvDescp.setText(establecimiento.get(TAG_DESCRIPCION));
            TextView tvDirec = (TextView) rootView
                    .findViewById(R.id.textViewDirec);
            tvDirec.setText(establecimiento.get(TAG_DIRECCION));
            TextView tvLocal = (TextView) rootView
                    .findViewById(R.id.textViewLocalidad);
            tvLocal.setText(establecimiento.get(TAG_LOCALIDAD));
            TextView tvProv = (TextView) rootView
                    .findViewById(R.id.textViewProv);
            tvProv.setText(establecimiento.get(TAG_PROVINCIA));
            TextView tvCodPostal = (TextView) rootView
                    .findViewById(R.id.textViewCodigo);
            tvCodPostal.setText(establecimiento.get(TAG_CODIGOPOSTAL));
            TextView tvEmail = (TextView) rootView
                    .findViewById(R.id.textViewWeb);
            tvEmail.setText(establecimiento.get(TAG_EMAIL));
            TextView tvTlf1 = (TextView) rootView
                    .findViewById(R.id.textViewTlf1);
            tvTlf1.setText(establecimiento.get(TAG_TLF1));
            TextView tvTlf2 = (TextView) rootView
                    .findViewById(R.id.textViewTlf2);
            tvTlf2.setText(establecimiento.get(TAG_TLF2));
        

        favButton.setOnClickListener(new OnClickListener() 

            @Override
            public void onClick(View arg0) 
                // TODO Auto-generated method stub
                // favButton.setActivated(true);

                editor.edit().putBoolean(establecimiento.get(TAG_ID),
                        !editor.getBoolean(establecimiento.get(TAG_ID), false)).commit();

            
        );
        return rootView;

    

    @Override
    public void onPause() 
        // TODO Auto-generated method stub
        super.onPause();
        editor.edit().commit();
    

    @Override
    public void onActivityCreated(Bundle savedInstanceState) 
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);

    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        // TODO Auto-generated method stub

        switch (item.getItemId()) 
        case (R.id.action_back):
            getFragmentManager().popBackStackImmediate();
            break;

        default:
            getActivity().onBackPressed();
            break;
        
        return super.onOptionsItemSelected(item);

    


编辑适配器类

我一直在苦苦挣扎,我已经解决了第一个问题。当回收视图更改行时,它会丢失复选框的状态并导致复选框不断更改其状态。我通过创建一个新的 Establecimiento 类来保存所有数据,然后在调用适配器之前创建了一个 ArrayList,将状态与其他值一起保存。我已经更新了我的适配器类以反映这种情况,现在复选框始终保持其状态,但是当您单击选项菜单并且在发生这种情况时弹出选项菜单时,复选框会更改它们的状态,然后当您单击其他位置时它会恢复正常状态

【问题讨论】:

这听起来像是适配器的问题。你能发布它的代码(特别是getView())吗? 谢谢@matiash,但我不这么认为,因为在其他视图(没有列表视图)中它的行为完全相同。我已经用更多信息编辑了我的问题。 if (sharedP.getBoolean(String.valueOf(position), false)) 您在共享首选项中的哪个位置保存此值? 我认为当您选中或取消选中复选框时,您会有一些监听器。仅监听 checkbox 而不是整个 listview 项 @GPRathour 我为屏幕截图的最后一个片段添加了类,该片段没有列表视图并且仍然具有相同的行为。我认为您必须是对的,但我还没有解决方法.. 【参考方案1】:

这里有问题:

    if (sharedP.getBoolean(String.valueOf(position), false)) 
        checkFav.setChecked(true);
    

您将检查设置为 true,但从不设置为 false。这意味着,当视图被回收然后重新用于不同的行时,即使它们不是收藏夹,它们也会显示为收藏夹。

这应该是这样的:

    boolean isFav = sharedP.getBoolean(String.valueOf(position), false);
    checkFav.setChecked(isFav);

【讨论】:

感谢您的回答,我已经更新了我的 Adapter 类并解决了第一个问题,但我仍然遇到“选项菜单更改复选框状态”的问题。我不再使用该行了。 【参考方案2】:

好吧,我想我终于知道发生了什么事。我正在为星形图像使用自定义可绘制对象(有两个图像,一个用于选中,一个用于未选中)这是我的星形可绘制对象:

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- Enabled states -->

    <item android:state_checked="true" android:state_window_focused="false"
          android:state_enabled="true"
          android:drawable="@drawable/ic_action_not_important" />
    <item android:state_checked="false" android:state_window_focused="false"
          android:state_enabled="true"
          android:drawable="@drawable/ic_action_important_cb" />

    <item android:state_checked="true" android:state_pressed="true"
          android:state_enabled="true"
          android:drawable="@drawable/ic_action_important_cb" />
    <item android:state_checked="false" android:state_pressed="true"
          android:state_enabled="true"
          android:drawable="@drawable/ic_action_not_important" />

    <item android:state_checked="true" android:state_focused="true"
          android:state_enabled="true"
          android:drawable="@drawable/ic_action_important_cb" />
    <item android:state_checked="false" android:state_focused="true"
          android:state_enabled="true"
          android:drawable="@drawable/ic_action_not_important" />

    <item android:state_checked="false"
          android:state_enabled="true"
          android:drawable="@drawable/ic_action_not_important" />
    <item android:state_checked="true"
          android:state_enabled="true"
          android:drawable="@drawable/ic_action_important_cb" />


</selector>

我只是有一种预感,我已经删除了我的自定义图像,而是改用了 @android/drawable="btn_star"(我不喜欢它,因为它是一个非常旧的设计并且破坏了我的应用程序的整体外观) 但是有了这个资源,现在的行为是完全正常的,所以我认为我的自定义可绘制对象有问题,但找不到它是什么

【讨论】:

以上是关于单击操作栏项目复选框时,更改其状态的主要内容,如果未能解决你的问题,请参考以下文章

gridview中的第一项在AdapterView.OnItemClickListener中不会更改

React Redux 表更新行

在更改 div 内的任何复选框时触发一个函数

通过列表框项目选择c#更改复选框的状态

Checkbox 失去其选中状态,并使用 Telerik RadDataPager 单击事件

在复选框状态更改时从回收器视图适配器更新 sqlite 数据库