首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在显示后检测每个RecyclerView项目

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

Stack Overflow用户
提问于 2019-04-01 02:04:28
回答 3查看 11.7K关注 0票数 8

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

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

但是我不能检测到什么时候每个项目都加载到屏幕上了!是否有任何方法需要调用才能检测呈现的每个项目

代码语言:javascript
复制
E.g 1st RecyclerView item displayed -> play sound
    2st RecyclerView item displayed -> play sound...

我的Adapter类看起来像这样-

代码语言:javascript
复制
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;
    .........
    .........

我从onCreated()方法调用这个initComponent()方法。你能给我一些建议吗?我应该怎么做才能达到上面描述的目标?

代码语言:javascript
复制
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();
        }
    });
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-04-10 03:34:23

您需要为TTS添加监听器。然后更新你的RecyclerView,在演讲开始和结束时显示正确的图像。

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

下面是我的MainActivity类的主要部分。

代码语言:javascript
复制
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) {
    }
}
票数 1
EN

Stack Overflow用户

发布于 2019-08-11 15:43:08

您需要覆盖onViewAttachedToWindowonViewDetachedFromWindow。但是为了检测holer类型,你需要像这样的getItemViewType()

代码语言:javascript
复制
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

    }
}
票数 4
EN

Stack Overflow用户

发布于 2019-04-11 14:24:52

如果我正确理解了您的问题,您希望在加载RecyclerView中的项目时播放声音。

因此,我想在这里想一个变通的办法。您可以考虑在播放前一个项目的声音后添加一个项目。

我想为我试图解释的东西提供一个伪代码。如果您的声音已经停止播放,您可以考虑使用MediaPlayer.OnCompletionListener进行收听,然后将下一项添加到RecyclerView中,然后调用适配器上的notifyDataSetChanged将下一项加载到RecyclerView中。

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

代码语言:javascript
复制
// Declare a function in your adapter which adds new item in the RecyclerView
public void addItem(Multiples item) {
    items.add(item);
    notifyItemInserted(items.size());
}

现在,在设置RecyclerViewActivity中,需要具有以下数组。

代码语言:javascript
复制
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(); 

如下所示修改您的函数。

代码语言:javascript
复制
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中添加元素。

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

代码语言:javascript
复制
private void addItemInRecyclerViewAndPlaySound() {

    soundToBePlayed++;

    adapter.addItem(allItems.get(soundToBePlayed));
    recyclerView.scrollToPosition(adapter.getItemCount() - 1);

    Integer soundId = soundList.get(soundToBePlayed);

    MediaPlayer mp = MediaPlayer.create(this, soundId);

    if (mp.isPlaying()) {
        mp.stop();
        mp.release();
        mp = MediaPlayer.create(this, soundId);
        mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            public void onCompletion(MediaPlayer mp) {
                // Call this function again to add next item
                // and play the next sound at the same time
                if(soundToBePlayed < allItems.size() - 1)
                    addItemInRecyclerViewAndPlaySound();
            }
        });
    }

    mp.start();
}

我还没有测试代码,但是,我想你已经明白了。这也可以使用适配器内部的interface很好地实现。实现技术是你的选择。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55443865

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档