Вопрос:

Как обнаружить каждый элемент RecyclerView после его отображения

java android android-recyclerview recycler-adapter android-viewholder

3330 просмотра

4 ответа

977 Репутация автора

Я хочу обнаружить каждый элемент в моем 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();
        }
    });
}
Автор: Donkey Источник Размещён: 31.03.2019 06:04

Ответы (4)


0 плюса

19 Репутация автора

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

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

Автор: Amin Mastani Размещён: 31.03.2019 06:09

0 плюса

1542 Репутация автора

Решение

Вам нужно добавить слушателя для 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) {
    }
}
Автор: Andrew Churilo Размещён: 09.04.2019 07:34

0 плюса

15693 Репутация автора

Если я правильно понял вашу проблему, вы хотите воспроизвести звук при 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 - ваш выбор.

Автор: Reaz Murshed Размещён: 11.04.2019 06:24

0 плюса

41 Репутация автора

вам нужно переопределить onViewAttachedToWindowи onViewDetachedFromWindow. но для определения типа дырокола вам нужно 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

    }
}
Автор: saeid aslami Размещён: 11.08.2019 07:43
Вопросы из категории :
32x32