web-dev-qa-db-ja.com

表示された後の各RecyclerViewアイテムの検出方法

ユーザーに表示された後、 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();
        }
    });
}
_
6
Dan

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) {
    }
}
1
Andrew Churilo

アダプターで単にonViewAttachedToWindow(VH)を使用できます。 https://developer.Android.com/reference/Android/support/v7/widget/RecyclerView.Adapter.html#onViewAttachedToWindow(VH) を参照してください

更新:

ご存知のように、RecyclerViewは、各項目に対して1回だけ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
    }
}

それが役に立てば幸い!

0
Amin Mastani

問題を正しく理解できた場合、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を使用して適切に実装することもできます。不和のテクニックはあなたの選択です。

0
Reaz Murshed