简体   繁体   English

如何在从活动类填充ListView的非活动类中正确设置setOnItemClickListener

[英]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. 我的ListView是根据用户在非活动类中输入EditText的内容从HashMap动态创建的。 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. 我之所以认为它与setOnItemClickListener有关,是因为当我在OnCreate方法的Activity类中手动设置ListView值时,它可以工作。 The non-activity class contains a couple of methods for such as AsyncTask and a recursion method. 非活动类包含用于AsyncTask和递归方法的几个方法。

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 . 在上面的代码之上,我不久前还以为我解决了它,并在onCreate方法的活动类中创建了onItemClickListener并使用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. AsyncTask可以设置OnClickListenersonPostExecute方法之一onPreExecute方法。
You cannot add OnClickListener or do any UI operations in the doInBackground method, since there you are making the network operations. 您不能在doInBackground方法中添加OnClickListener或执行任何UI操作,因为您正在执行网络操作。

So you can set the OnClickListener regullary: 因此,您可以设置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. 在幕后,ArrayAdapter使用提供给它的ArrayList(或数组)中每个条目的toString()方法,并填充在您使用的构造函数的第二个参数中指定的布局。

If wordSuccess array list is not empty, then your mapping of the entry to this layout is failing. 如果wordSuccess数组列表不为空,则该条目到此布局的映射失败。 ArrayAdapter expects a TextView or something that is a derivative of that as the second argument in that constructor. ArrayAdapter希望将TextView或其派生类作为该构造函数中的第二个参数。 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. 您的lv_displaywords_wordentry布局文件可能不是简单的TextView,或者它包含用某种ViewGroup容器包装的TextView。 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. 由于您显示的是简单列表项,因此建议您使用android.R.layout.simple_list_item_1,如果数组列表不为空,则应该会看到显示的单词。

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. 就像我猜到的那样,从注释中可以理解,您正在尝试将解析为布局的布局传递给ArrayAdapter中的ListView而不是TextView。 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). 您可以正常使用ListView,但是适配器无法将数组列表中的String条目映射到ListView对象(因为ListView代表整个集合,而映射是一对一进行的)。 This is why you need to pass a TextView (or a custom subclass or variation of it). 这就是为什么您需要传递TextView(或其自定义子类或它的变体)的原因。 Use the android supplied list item layout and you should get a standard TextView. 使用android提供的列表项布局,您应该获得标准的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); 
   }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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