代码之家  ›  专栏  ›  技术社区  ›  Dan

如何检测屏幕上显示的每个RecyclerView项目

  •  0
  • Dan  · 技术社区  · 5 年前

    我想检测我的数据库中的每个项目 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();
            }
        });
    }
    
    2 回复  |  直到 5 年前
        1
  •  4
  •   saeid aslami    5 年前

    你需要重写 onViewAttachedToWindow onViewDetachedFromWindow . 但要检测holer类型,您需要 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
    
        }
    }
    
        2
  •  1
  •   Community pid    4 年前

    看见 https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onViewAttachedToWindow(VH)

    如你所知 RecyclerView OnBindViewHolder 每件物品仅限一次。

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

    所以你可以用 onViewAttachedToWindow

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

    这可以作为一个合理的信号,表明 视图即将被用户看到。

    您可以这样使用它:

    public class Adapter extends RecyclerView.Adapter<MyViewHolder> {
       
        // rest of your code
    
       
        @Override
        public void onViewAttachedToWindow(MyViewHolder holder) {
             super.onViewAttachedToWindow(holder);
            // play your sound
        }
    }
    
    

        3
  •  1
  •   Andrew Churilo    5 年前

    您需要为TTS添加侦听器。然后更新您的 RecyclerView

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

    这里是我的主要部分 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) {
        }
    }
    
        4
  •  0
  •   Reaz Murshed vir us    5 年前

    如果我正确地理解了您的问题,则您希望在 RecyclerView 已加载。

    因此,我想在这里想出一个解决办法。您可能会考虑在前一个项目的声音播放之后添加一个项目。

    我想为我试图解释的内容提供一个伪代码。你可以考虑使用 MediaPlayer.OnCompletionListener 如果您的声音停止播放,然后将下一项添加到 回收视图 然后打电话 notifyDataSetChanged 回收视图 .

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

    // Declare a function in your adapter which adds new item in the RecyclerView
    public void addItem(Multiples item) {
        items.add(item);
        notifyItemInserted(items.size());
    }
    

    现在在你的 Activity 你在哪里设置的 回收视图 ,您需要具有以下阵列。

    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 项目 . 因为我们将向 项目 稍后。

    onCreate 通话后活动的功能 initComponent 功能。函数应该如下所示。

    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