显示每个RecyclerView项目后如何检测

时间:2019-03-31 18:04:28

标签: java android android-recyclerview recycler-adapter android-viewholder

我想在RecylerView中的每一项显示给用户后对其进行检测。

基本上,我试图在每个项目加载到屏幕上后播放声音。

但是每当屏幕上加载了每个项目时,我都无法检测到!我必须调用任何方法来检测渲染的每个项目

E.g 1st RecyclerView item displayed -> play sound
    2st RecyclerView item displayed -> play sound...

我的适配器类看起来像这样-

public class AdapterListAnimation extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<Multiples> items = new ArrayList<>();

    private Context ctx;
    private OnItemClickListener mOnItemClickListener;
    private int animation_type = 0;
    .........
    .........

我正在从initComponent()方法中调用此onCreated()方法。您能为我如何实现上述目标提供建议吗?

private void initComponent() {
    recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setHasFixedSize(true);
    items = DataGenerator.getPeopleData(this,of,value);
    setAdapter();

    /* MediaPlayer mp=MediaPlayer.create(this, R.raw.sword);
    if (mp.isPlaying()) {
        mp.stop();
        mp.release();
        mp = MediaPlayer.create(this, R.raw.sword);
    } mp.start();*/
}

private void setAdapter() {
    // Set data and list adapter
    mAdapter = new AdapterListAnimation(this, items, animation_type);
    recyclerView.setAdapter(mAdapter);

    // on item list clicked
    mAdapter.setOnItemClickListener(new AdapterListAnimation.OnItemClickListener() {
        @Override
        public void onItemClick(View view, com.math.multiplication.model.Multiples obj, int position) {
            Snackbar.make(parent_view, "Item " + obj.first + " clicked", Snackbar.LENGTH_SHORT).show();
        }
    });
}

4 个答案:

答案 0 :(得分:2)

您需要覆盖onViewAttachedToWindowonViewDetachedFromWindow。但是要检测破洞类型,您需要getItemViewType()就像这样:

public class PostAdapter extends RecyclerView.Adapter {

@Override
public int getItemViewType(int position) {
    switch (types.get(position)){
        case 1:
            return 1;
        case 2:
            return 2;
        default:
            return position;


    }
}
@Override
public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) {
    super.onViewAttachedToWindow(holder);
    if (holder.getItemViewType() == 1){
        //play song

    }

}

@Override
public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder holder) {
    super.onViewDetachedFromWindow(holder);
    if (holder.getItemViewType() == 1){
        //pause song

    }
}

答案 1 :(得分:0)

您只需在适配器中使用onViewAttachedToWindow(VH)。 参见https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onViewAttachedToWindow(VH)

更新

您知道,RecyclerView对于每个项目仅被调用一次OnBindViewHolder

  

如果项目的位置在数据集中发生更改,RecyclerView将不会再次调用此方法,除非该项目本身无效或无法确定新位置。

因此您可以使用onViewAttachedToWindow

  

(onViewAttachedToWindow)在此适配器创建的视图附加到窗口时调用。

     

这可以用作合理的信号,表明用户将看到 视图。 。如果适配器先前释放了onViewDetachedFromWindow中的任何资源,则应将这些资源在这里恢复。

您可以像这样使用它:

public class Adapter extends RecyclerView.Adapter<MyViewHolder> {

    // rest of your code


    @Override
    public void onViewAttachedToWindow(MyViewHolder holder) {
         super.onViewAttachedToWindow(holder);
        // play your sound
    }
}

希望有帮助!

答案 2 :(得分:0)

您需要为TTS添加侦听器。然后更新您的RecyclerView以在语音开始和结束时显示正确的图像。

我已经创建了一个测试项目来展示如何实现它。 Here,您会看到它是如何工作的。 Here是我的github存储库。

这是我的MainActivity类的主要部分。

private void initTts() {
    tts = new TextToSpeech(this, this);
    tts.setLanguage(Locale.US);
    tts.setOnUtteranceProgressListener(new MyListener());
}

@Override
public void onInit(int status) {
    playSound(0);
}

private void playSound(int index) {
    HashMap<String, String> hashMap = new HashMap<>();
    hashMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, String.valueOf(index));
    tts.speak(data.get(index), TextToSpeech.QUEUE_ADD, hashMap);
}

class MyListener extends UtteranceProgressListener {
    @Override
    public void onStart(String utteranceId) {
        int currentIndex = Integer.parseInt(utteranceId);
        mMainAdapter.setCurrentPosition(currentIndex);
        handler.post(new Runnable() {
            @Override
            public void run() {
                mMainAdapter.notifyDataSetChanged();
            }
        });
    }

    @Override
    public void onDone(String utteranceId) {
        int currentIndex = Integer.parseInt(utteranceId);
        mMainAdapter.setCurrentPosition(-1);
        handler.post(new Runnable() {
            @Override
            public void run() {
                mMainAdapter.notifyDataSetChanged();
            }
        });
        if (currentIndex < data.size() - 1) {
            playSound(currentIndex + 1);
        }
    }

    @Override
    public void onError(String utteranceId) {
    }
}

答案 3 :(得分:0)

如果我正确理解了您的问题,则想在装入RecyclerView中的项目时播放声音。

因此,我想在这里考虑一种解决方法。您可以考虑在播放上一个项目的声音之后添加一个项目。

我想为我要解释的内容提供一个伪代码。如果您的声音已停止播放,则可以考虑使用documentation进行监听,然后将下一项添加到RecyclerView,然后在适配器上调用notifyDataSetChanged以将下一项加载到{ {1}}。

因此,您可能首先需要在适配器中进行以下修改。

RecyclerView

现在在设置// Declare a function in your adapter which adds new item in the RecyclerView public void addItem(Multiples item) { items.add(item); notifyItemInserted(items.size()); } 的{​​{1}}中,您需要具有以下数组。

Activity

如下修改功能。

RecyclerView

随着ArrayList<Multiples> allItems = new ArrayList<Multiples>(); // This list will contain all the data int soundToBePlayed = -1; // Initialize the value with -1 ArrayList<Integer> soundList = getAllSoundsInAList(); 从构造函数中删除,您还需要修改适配器的构造函数。只需删除采用private void initComponent() { recyclerView = (RecyclerView) findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setHasFixedSize(true); allItems = DataGenerator.getPeopleData(this,of,value); setAdapter(); } private void setAdapter() { mAdapter = new AdapterListAnimation(this, animation_type); // Do not pass the items list recyclerView.setAdapter(mAdapter); // .. Your item click listener goes here } 的变量即可。因为稍后我们将向items添加元素。

然后,您需要编写另一个函数,在调用items函数之后,需要在活动的items函数中调用该函数。该函数应如下所示。

onCreate

我尚未测试代码,但是,我认为您已经明白了。也可以在适配器内部使用initComponent来实现。输精管技巧是您的选择。