【问题标题】:Is it possible to get the position of views inside ViewHolder for the RecyclerView?是否可以获取 RecyclerView 的 ViewHolder 中的视图位置?
【发布时间】:2025-11-29 21:15:01
【问题描述】:

我拥有的 ViewHolder 包含 RecycleView 的每个项目所需的视图,它们是两个 TextView、PlayPauseView 和 AppCompatSeekBar。在构造函数中,我已将它们初始化为我的布局的 id,并准备好让我的 Adapter 类扩展它。问题是我有这个 PlayPauseView 需要在正确的位置切换才能正常工作,因为如果我在另一个位置按下视图,之前的位置仍然会被切换。这是一张便于理解的图片。

黄色表示它正在播放,但是两个不能同时播放,所以我希望在 RecyclerView 项目中获得视图的位置。

这是来自 Holder 类

TextView mInstrumentalName, mProducer;
PlayPauseView mPlayButton; // Need to add pause/stop
AppCompatSeekBar mMusicSeekbar;

ItemClickListener itemClickListener;

public TrackHolder(View itemView) {
    super(itemView);

    mInstrumentalName = (TextView) itemView.findViewById(R.id.instrumental_name);
    mProducer = (TextView) itemView.findViewById(R.id.producer);
    mPlayButton = (PlayPauseView) itemView.findViewById(R.id.play_pause);
    mMusicSeekbar = (AppCompatSeekBar) itemView.findViewById(R.id.music_seekbar);



    itemView.setOnClickListener(this);
}

这是来自适配器类

@Override
public void onBindViewHolder(@NonNull final TrackHolder holder, final int position) {
    holder.mInstrumentalName.setText(tracks.get(position).getInstrumentalName());
    holder.mProducer.setText(tracks.get(position).getProducer());


    holder.mPlayButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            holder.mPlayButton.toggle();
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            if (mediaPlayer.isPlaying()) {

                mediaPlayer.reset();
                try {
                    mediaPlayer.setDataSource(tracks.get(position).getMusicLink());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mediaPlayer) {
                        mediaPlayer.start();
                    }
                });
                mediaPlayer.prepareAsync();

            } else {
                try {
                    mediaPlayer.setDataSource(tracks.get(position).getMusicLink());
                    previous_link = tracks.get(position).getMusicLink();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mediaPlayer) {
                        mediaPlayer.start();
                    }
                });
                mediaPlayer.prepareAsync();
            }


        }
    });

    mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) {
            mediaPlayer.release();
        }
    });

    holder.setItemClickListener(new ItemClickListener() {
        @Override
        public void onItemClick(View v, int pos) {
            Toast.makeText(context, Integer.toString(tracks.size()), Toast.LENGTH_SHORT).show();
        }
    });
}

【问题讨论】:

  • 是的,您可以显示您的代码吗?
  • 是的,我现在已经添加了。
  • 你的问题是什么? "position of view inside ViewHolder" 是什么意思?
  • @pskink 就像我希望能够在位置 0 中重新切换 PlayPauseView,同时在位置 2 中切换 PlayPauseView。
  • 所以使用ViewHolder#getAdapterPosition()方法

标签: android android-recyclerview android-viewholder


【解决方案1】:

如果你想在你的视图持有者类中获得位置,那么你可以在你的类中调用getAdapterPosition()。这将返回您在视图持有者类中的点击位置

【讨论】:

    【解决方案2】:

    我终于找到了解决办法。所以我所做的不是专注于 ViewHolder 内部的视图,而是刷新/更新了 RecyclerView 中的整个项目,这意味着它将刷新前一个项目的切换状态。如果将来有人在同一个问题上遇到任何问题,这里会截取一段代码。

                private int start_notifying = 0;
                private int previous_pos = -1;
    

    所以开始通知从 0 开始,因为您不想刷新项目,直到您至少切换一次播放按钮,并且当您想按下不同的列表项时,将当前位置设置为上一个位置。然后您递增,以便您可以在按下下一个项目时开始刷新项目。使用 notifyItemChanged(previous_pos) 刷新上一个被按下位置的项目,使播放按钮回到正常状态。

                if (start_notifying > 0) {
                    notifyItemChanged(previous_pos);
                    previous_pos = position;
                } else {
                    previous_pos = holder.getAdapterPosition();
                    Log.d("previous_pos", Integer.toString(holder.getAdapterPosition()));
                    start_notifying++;
                }
    

    【讨论】:

      最近更新 更多