Как обнаружить каждый элемент RecyclerView после его отображения - PullRequest
5 голосов
/ 31 марта 2019

Я хочу обнаружить каждый элемент в моем 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();
        }
    });
}

Ответы [ 3 ]

0 голосов
/ 09 апреля 2019

Вам нужно добавить слушателя для TTS.Затем обновите ваш RecyclerView, чтобы показать правильное изображение, когда речь начинается и заканчивается.

Я создал тестовый проект, чтобы показать, как его можно реализовать. Здесь вы можете увидеть, как это работает. Здесь - это мой репозиторий 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) {
    }
}
0 голосов
/ 11 апреля 2019

Если я правильно понял вашу проблему, вы хотите воспроизвести звук при загрузке элемента в RecyclerView.

Поэтому я хотел бы подумать об обходном пути здесь.Вы можете рассмотреть возможность добавления элемента после воспроизведения звука для предыдущего элемента.

Я хотел бы предоставить псевдокод для того, что я пытаюсь объяснить.Вы можете использовать MediaPlayer.OnCompletionListener для прослушивания, если ваш звук перестал воспроизводиться, а затем добавить следующий элемент в RecyclerView и затем вызвать notifyDataSetChanged на вашем адаптере, чтобы загрузить следующий элемент в 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());
}

Теперь в вашем 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.Функция должна выглядеть следующим образом.

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 внутри адаптераТехника imeplemntation - ваш выбор.

0 голосов
/ 31 марта 2019

Вы можете просто использовать 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
    }
}

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...