使用自定义适配器时,OnItemClickListener无法在DialogFragment中工作

时间:2015-08-04 15:30:51

标签: java android listview checkbox listadapter

我想显示一个标题复选框列表(本例中为行星),当我点击其中一个复选框(此示例中的Toast和Log)时会发生一些事情。但是要显示复选框,我需要使用自定义适配器(当我使用SimpleAdapter时一切正常),但OnItemClickListener不再有效。复选框选中/取消选中,但我无法让DialogFragment确认已点击任何内容。

还有一个搜索栏,可以在您键入时动态过滤列表,但我认为这不会产生影响,因为它与SimpleAdapter一起正常工作。

这是一些有趣的代码:

MainActivity.java

import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        DialogFragment fragment = SearchDialogFragment.newInstance();
        fragment.show(getSupportFragmentManager(), "SearchDialog");
    }
}

SearchDialogFragment.java

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SearchDialogFragment extends DialogFragment
{
    private List<Map<String, Boolean>> planetsList;
    private ListView listView;
    private List<String> selectedPlanets;

    public static SearchDialogFragment newInstance()
    {
        return new SearchDialogFragment();
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        LayoutInflater inflater = getActivity().getLayoutInflater();
        View view = inflater.inflate(R.layout.fragment_search_dialog, null);

        builder.setTitle("List of planets");
        builder.setView(view);

        listView = (ListView) view.findViewById(R.id.fragment_list_view);

        selectedPlanets = new ArrayList<>();
        createPlanetsList("");
        resetAdapter();

        /**
         * NOT WORKING
         */
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
        {
            public void onItemClick(AdapterView<?> parentAdapter, View view, int position, long id)
            {
                Toast.makeText(getActivity(), "CLICK!!!!", Toast.LENGTH_SHORT).show();
                Log.e("SDF", "CLICK!!!!");
            }
        });
        /**
         * /NOT WORKING
         */

        SearchView search = (SearchView) view.findViewById(R.id.fragment_search_view);
        search.setQueryHint("Search list");

        // Reacts to the search bar
        search.setOnQueryTextListener(new SearchView.OnQueryTextListener()
        {
            @Override
            public boolean onQueryTextSubmit(String query)
            {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String searchText)
            {
                updateDisplayList(searchText);
                return false;
            }
        });

        return builder.create();
    }

    @Override
    public void onAttach(Activity activity)
    {
        super.onAttach(activity);
    }

    @Override
    public void onDetach()
    {
        super.onDetach();
    }

    private void createPlanetsList(String searchText)
    {
        planetsList = new ArrayList<>();

        addPlanet("Mercury", searchText);
        addPlanet("Venus", searchText);
        addPlanet("Earth", searchText);
        addPlanet("Mars", searchText);
        addPlanet("Jupiter", searchText);
        addPlanet("Saturn", searchText);
        addPlanet("Uranus", searchText);
        addPlanet("Neptune", searchText);
    }

    private void addPlanet(String planetName, String searchText)
    {
        if (planetName.toLowerCase().contains(searchText.toLowerCase()))
        {
            HashMap<String, Boolean> planet = new HashMap<>(1);
            boolean isSelected = selectedPlanets.contains(planetName);
            planet.put(planetName, isSelected);

            planetsList.add(planet);
        }
    }

    private void resetAdapter()
    {
        // It worked when I used this instead of my custom adapter
        /*
        SimpleAdapter simpleAdapter = new SimpleAdapter(
                getActivity(), // Context
                planetsList, // Data list
                android.R.layout.select_dialog_multichoice, // Row layout
                new String[] {"planet"}, // Keys for list
                new int[] {android.R.id.text1}); // View ID used to show the data
        listView.setAdapter(simpleAdapter);
        */

        MultiSelectAdapter adapter = MultiSelectAdapter.getAdapter(getActivity(), planetsList, selectedPlanets);
        listView.setAdapter(adapter);
    }

    private void updateDisplayList(String searchText)
    {
        createPlanetsList(searchText);
        resetAdapter();
    }
}

MultiSelectAdapter.java

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;

import java.util.List;
import java.util.Map;

public class MultiSelectAdapter extends ArrayAdapter
{
    private Context context;
    private List<Map<String, Boolean>> planetsList;

    private static List<String> selectedPlanets;

    public static MultiSelectAdapter getAdapter(Context context, List<Map<String, Boolean>> objects, List<String> dialogSelectedPlanets)
    {
        selectedPlanets = dialogSelectedPlanets;

        return new MultiSelectAdapter(context, android.R.id.text1, objects);
    }

    private MultiSelectAdapter(Context context, int resource, List<Map<String, Boolean>> objects)
    {
        super(context, resource, objects);

        this.context = context;
        this.planetsList = objects;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowView = inflater.inflate(R.layout.fragment_row_layout, parent, false);

        CheckBox checkBox = (CheckBox) rowView.findViewById(R.id.row_check_box);
        String planetName = (String) planetsList.get(position).keySet().toArray()[0];
        checkBox.setText(planetName);

        if (selectedPlanets.contains(planetName))
        {
            checkBox.setChecked(true);
        }

        return rowView;
    }
}

fragment_search_dialog.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="lomax.mysearchinterface.SearchDialogFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <SearchView
        android:id="@+id/fragment_search_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginEnd="30dp"
        android:layout_marginRight="30dp"
        android:iconifiedByDefault="false"/>

    <ListView
        android:id="@+id/fragment_list_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

</LinearLayout>

fragment_row_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <CheckBox
        android:id="@+id/row_check_box"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textAllCaps="true"
        android:text="Planet name"
        android:focusable="false"/>

</LinearLayout>

1 个答案:

答案 0 :(得分:0)

经过互联网争取一些想法后,我偶然发现了解决这个问题的方法。在我的适配器类的getView(...)方法中:

checkBox.setOnCheckedChangeListener(this);

并让我的适配器类实现:

implement CompoundButton.OnCheckedChangeListener

这似乎有效,无需更改行布局的XML或任何其他聪明。

希望这有助于下一个遇到这个问题的可怜的人......