简体   繁体   中英

How do I setOnItemClickListener correctly in a non-activity class that populates a ListView from an Activity Class

My ListView is created dynamically from a HashMap depending on what the user enters into an EditText in a non-activity class. The reason why I believe it is to do with the setOnItemClickListener is because it works when I set the ListView values manually in the Activity class in the OnCreate method. The non-activity class contains a couple of methods for such as AsyncTask and a recursion method.

Activity Class

public class WordEntry extends AppCompatActivity implements OnClickListener, OnItemClickListener {

//Variable's Declared

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.word_entry);

    /*Code for reading values into HashMap here*/

    btn_Resolve = (Button) findViewById(R.id.submit_word);
    btn_Resolve.setOnClickListener(this);

    //TODO Make list item's clickable.

    spin_options = (Spinner) findViewById(R.id.spin_choose_resolver_type);
    ArrayAdapter<CharSequence> spin_adapter = ArrayAdapter.createFromResource(this,
            R.array.resolver_options, R.layout.simpler_spinner_item);

    spin_adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
    spin_options.setAdapter(spin_adapter);
    lv_words = (ListView) findViewById(R.id.lv_word_display);

    /*This following two lines were a test to see if manually setting the adapter worked, it did. */
    //lv_words.setAdapter(spin_adapter);
    //lv_words.setOnItemClickListener(this);


}

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

    Log.i("HelloListView", "You clicked item: " + parent + " at position: " + position);

}


@Override
public void onClick(View v) {

    switch (v.getId()) {
        case R.id.submit_word:

            edt_WordEntry = (EditText) findViewById(R.id.word_entry_textbox);
            word = edt_WordEntry.getText().toString().toLowerCase();
            Pattern pattern = Pattern.compile("\\s");
            Matcher matcher = pattern.matcher(word);
            boolean space_found = matcher.find();
            View hideKey = this.getCurrentFocus();

            if (space_found) {
               edt_WordEntry.setText(R.string.no_spaces_allowed);

            } else {
                ResolveWord fixAnagram = new ResolveWord(word, this,wordHashSet);
                ResolveAllWords fixAnagramAll = new ResolveAllWords(word,this,wordHashSet);

                /*The following two lines are two other methods that I tried during debugging to try get it working. Separately of                  course and this debugging was for when the spinner was set to something other than "Anagram's"*/
                //fixAnagramAll.lv_words.setOnItemClickListener(new ResolveWord(word,this,wordHashSet));  
                //lv_words.setOnItemClickListener(new ResolveWord(word,this,wordHashSet));                           
                if(spin_options.getSelectedItem().toString().equals("Anagram;s")) {
                    hideKeyboard(this);
                    fixAnagram.execute();
                } else {
                    hideKeyboard(this);
                    fixAnagramAll.execute();
                }
            }
            break;

        default:
            break;
    }

}

Non Activity Class

public class ResolveWord extends  AsyncTask<Void, Integer, ArrayList<String>> implements OnItemClickListener {

 /*Variable's Declared*/


public ResolveWord(String letters, Activity wordEntryContext, HashSet<String> passedHashSet) {
    /*Variables initiated */

}


   /*Some code.....*/

@Override
protected void onPostExecute(ArrayList<String> wordSuccess) {

    /*Code which puts data into an arraylist so I can put into the array adadater that follows...*/

    ArrayAdapter<String> adapter = new ArrayAdapter<>(thisContext,R.layout.lv_displaywrods_wordentry,
            wordSuccess);

    //Ways I tried to get the ListView clickable in the non-activity class...
    lv_words.setAdapter(adapter);

    //lv_words.setOnItemClickListener(new WordEntry());
    //lv_words.setOnItemClickListener(this);

   /*lv_words.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        //I have a break point here to see if the string gets assigned during debugging after clicking a rowitem.
        String x = "Test";

    }
});*/

    //This always returns false
    boolean o = lv_words.hasOnClickListeners();
    //This always returns true
    boolean p = lv_words.isClickable();


}

On top of the above code I also made some edits shortly ago when I thought I had it solved and created an onItemClickListener in the activity class in the onCreate method and assigned this a value using getOnItemClickListener . I then passed it to the non-activity class through the constructor but this also failed to work.

In the AsyncTask you can set OnClickListeners in the onPostExecute method and one the onPreExecute method.
You cannot add OnClickListener or do any UI operations in the doInBackground method, since there you are making the network operations.

So you can set the OnClickListener regullary:

lv_words.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick() {
        // Do some coding...
    }
});

Behind the scenes, ArrayAdapter uses the toString() method of each entry in the ArrayList (or array) supplied to it and populates the layout specified in the second argument of the constructor you have used.

If wordSuccess array list is not empty, then your mapping of the entry to this layout is failing. ArrayAdapter expects a TextView or something that is a derivative of that as the second argument in that constructor. Your lv_displaywords_wordentry layout file is likely not a straightforward TextView or it contains a TextView wrapped with some kind of a ViewGroup container. Since you are displaying simple list items, I would recommend you use android.R.layout.simple_list_item_1 and if your array list is not empty you should see the words showing up.

EDIT:

As I guessed, from the comments, I understand you are trying to pass the layout that resolves to a ListView instead of a TextView in your ArrayAdapter. You can use the ListView normally but your adapter has no way of mapping the String entry in the array list to the ListView object (as the ListView represents the entire collection while mapping is done on a one to one basis). This is why you need to pass a TextView (or a custom subclass or variation of it). Use the android supplied list item layout and you should get a standard TextView.

您可以尝试为ResolveWord设置传承程序,以将WordEntry对象-wordEntry传递给ResolveWord,然后在onPostExecute(...)中编写: lv_words.setOnItemClickListener(wordEntry);

It's hard to understand you, but I think you are going to archive following thing:

public class ResolveWord extends  AsyncTask<Void, Integer, ArrayList<String>> {
    private Activity wordEntryContext;

   public ResolveWord(String letters, Activity wordEntryContext, HashSet<String> passedHashSet) {
       this.wordEntryContext = wordEntryContext;
       /*Other variables initiated */ 
   } 

   @Override 
   protected void onPostExecute(ArrayList<String> wordSuccess) {
       // your code
       lv_words.setOnItemClickListener((OnItemClickListener)wordEntryContext); 
   }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM