2

I'm currently working on guessing game as a part of a learning process. In my app you basically have to guess one correct definition out of three. TextView provides a word, RecyclerView - three options. Words come from a text file.

I've learned how to change RecyclerView after i click on it. Word in TextView have to change as well, but i can't access it from Adapter class.

enter image description here

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var listNames = mutableListOf<String>()

        listMain.layoutManager = GridLayoutManager (this,3,1,false) as RecyclerView.LayoutManager?
        listMain.adapter = ItemAdapter(listNames)

        readDictionaryFile(listNames)
        wordGuess.text = listNames[0]
    }



    private fun readDictionaryFile(listNames: MutableList<String>) {
        val reader = Scanner(resources.openRawResource(R.raw.test))
        while (reader.hasNextLine()) {
            val line = reader.nextLine()
            val split = line.split(";")
            listNames.add(split[0])
        }
    }



class ItemAdapter(private val listNames: MutableList<String>): RecyclerView.Adapter<CustomViewHolder>() {

    //number of items
    override fun getItemCount(): Int {
        return listNames.size
    }

    override fun onCreateViewHolder(p0: ViewGroup, p1: Int): CustomViewHolder {
        val layoutInflater = LayoutInflater.from(p0.context)
        val cellForRow = layoutInflater.inflate(R.layout.list_layout, p0, false )
        return CustomViewHolder(cellForRow)
    }

    override fun onBindViewHolder(p0: CustomViewHolder, p1: Int) {
        val listTitle = listNames.get(p1)
        p0.view.listNamesView.text = listTitle
        p0.view.setOnClickListener {
            //do something
            notifyDataSetChanged()
        }

    }
shizhen
  • 12,251
  • 9
  • 52
  • 88

2 Answers2

1

You can do it this way:

Declare interface in your adapter:

public interface MyInterface{
public void foo();
}

Let Activity implement it:

public class MyActivity extends Activity implements MyInterface{
public void foo(){
    //do stuff
   }
}

Then pass your activity to RecyclerAdapter:

public MyAdapter extends BaseAdater{
private MyInterface listener;

public MyAdapter(MyInterface listener){
    this.listener = listener;
    }
}

And somewhere in adapter, when you need to call that Activity method:

listener.foo();

This answer is based on this question.

Payam Asefi
  • 2,677
  • 2
  • 15
  • 26
0

Pass a callback to your adapter.

class ItemAdapter(private val listNames: MutableList<String>, private val onNameClicked: (String) -> Unit): RecyclerView.Adapter<CustomViewHolder>() {

    //number of items
    override fun getItemCount(): Int {
        return listNames.size
    }

    override fun onCreateViewHolder(p0: ViewGroup, p1: Int): CustomViewHolder {
        val layoutInflater = LayoutInflater.from(p0.context)
        val cellForRow = layoutInflater.inflate(R.layout.list_layout, p0, false )
        return CustomViewHolder(cellForRow)
    }

    override fun onBindViewHolder(p0: CustomViewHolder, p1: Int) {
        val listTitle = listNames.get(p1)
        p0.view.listNamesView.text = listTitle
        p0.view.setOnClickListener {
            //do something
            onNameClicked(listTitle)
            notifyDataSetChanged()
        }

    }
}

In your MainActivity,

listMain.adapter = ItemAdapter(listNames) { name ->
    // Update your TextView or something
}

On another note, I see that the list in your adapter is mutable. I'd suggest to make it immutable as modifying the adapter dataset and not calling notifyDataSetChanged() is prone to bugs and not a good practice.

Froyo
  • 17,947
  • 8
  • 45
  • 73