質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

スクロール

スクロールとは、ディスプレイスクリーン上において連続的にコンテンツが滑っていくことを指します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

2713閲覧

ボタン押下時にrecyclerviewで作成されたスクロールを1つずつスライドさせる方法

roatt

総合スコア45

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

スクロール

スクロールとは、ディスプレイスクリーン上において連続的にコンテンツが滑っていくことを指します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2021/11/04 07:49

前提・実現したいこと

recyclerviewで作成されたスクロールを指ではなく、ボタンの押下で1スライドずつ動かしたいです。
例えば、No.1 No.2 No.3 No.4…とスクロールになっていて、No.1が画面の中心にある場合、
右ボタンを押すとNo.2が画面中心にスライドされるというような感じです。
※画面の向きはlandscapeで作成しています。

現状作成しているスクロールは以下のURLの「端の要素を中心にする」バージョンです。
これは必ず必要です。
(cardviewではなく、imagebuttonで作成していますが…)
https://ryuta46.com/1207

該当のソースコード

MainActivity.java

Java

1public class MainActivity extends AppCompatActivity { 2 3 ScrollController controller; 4 5 private static final Integer[] icons = { 6 R.drawable.A, 7 R.drawable.B, 8 R.drawable.C, 9 R.drawable.D, 10 R.drawable.E, 11 R.drawable.F, 12 R.drawable.G 13 }; 14 15 private static final String[] iconNames = { 16 "No.1", "No.2", "No.3", "No.4", "No.5", "No.6", "No.7" 17 }; 18 19 @Override 20 protected void onCreate(Bundle savedInstanceState) { 21 super.onCreate(savedInstanceState); 22 setContentView(R.layout.activity_main); 23 24 RecyclerView recyclerView = findViewById(R.id.recyclerView); 25 recyclerView.setHasFixedSize(true); 26 27 RecyclerView.LayoutManager rLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); 28 recyclerView.setLayoutManager(rLayoutManager); 29 30 List<Integer> itemImages = new ArrayList<>(Arrays.asList(icons)); 31 List<String> itemNames = new ArrayList<>(Arrays.asList(iconNames)); 32 33 RecyclerAdapter recyclerAdapter = new RecyclerAdapter(itemImages, itemNames); 34 recyclerView.setAdapter(recyclerAdapter); 35 36 controller = new ScrollController(); 37 recyclerView.addOnItemTouchListener(controller); 38 39 //中央にスナップ 40 LinearSnapHelper snapHelper = new LinearSnapHelper(); 41 snapHelper.attachToRecyclerView(recyclerView); 42 43 //アイテムが最初または最後であっても、強制的に中央に配置 44 recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() { 45 @Override 46 public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 47 int edgeMargin = (parent.getWidth() - view.getLayoutParams().width) / 2; 48 int position = parent.getChildAdapterPosition(view); 49 50 if (position == 0) { 51 outRect.left = edgeMargin; 52 } 53 if (position == state.getItemCount() - 1) { 54 outRect.right = edgeMargin + 11; 55 } 56 } 57 }); 58 59 ImageButton left_button = findViewById(R.id.left_button); 60 ImageButton right_button = findViewById(R.id.right_button); 61 62 left_button.setOnClickListener(new View.OnClickListener() { 63 @Override 64 public void onClick(View view) { 65 //ここに何を書いていいのかわからない 66 } 67 68 } 69 }); 70 71 right_button.setOnClickListener(new View.OnClickListener() { 72 @Override 73 public void onClick(View view) { 74 //ここに何を書いていいのかわからない 75 } 76 }); 77 } 78}

RecyclerAdapter.java

Java

1public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> { 2// final Context context; 3// private int itemCount; 4 5 private final List<Integer> iImages; 6 private final List<String> iNames; 7 private View.OnClickListener m_listener; 8 int m_line; 9 10 static class ViewHolder extends RecyclerView.ViewHolder { 11 ImageButton imagebutton; 12 TextView textview; 13 14 ViewHolder(View v) { 15 super(v); 16 imagebutton = v.findViewById(R.id.imageButton); 17 textview = v.findViewById(R.id.textView14); 18 } 19 } 20 21 RecyclerAdapter(List<Integer> itemImages, List<String> itemNames) { 22 this.iImages = itemImages; 23 this.iNames = itemNames; 24 } 25 26 public void setOnItemClickListener(View.OnClickListener listener){ 27 m_listener = listener; 28 } 29 30 @Override 31 @NonNull 32 public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 33 View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_row, parent, false); 34 return new ViewHolder(view); 35 } 36 37 @Override 38 public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 39 holder.imagebutton.setImageResource(iImages.get(position)); 40 holder.textview.setText(iNames.get(position)); 41 42 final int pos = position; 43 // リスト上のボタンが押された時に上で登録したクリックリスナーを呼び出してあげる 44 holder.imagebutton.setOnClickListener(new View.OnClickListener() { 45 @Override 46 public void onClick(View view) { 47 m_line = pos; 48 m_listener.onClick(view); 49 } 50 }); 51 } 52 public int getLine(){ 53 return m_line; //行数を取得 54 } 55 56 @Override 57 public int getItemCount() { 58 return iImages.size(); 59 } 60}

land\recycler_row.xml

xml

1<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:app="http://schemas.android.com/apk/res-auto" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="450dp" 5 android:layout_height="match_parent" 6 android:padding="15dp"> 7 8 <ImageButton 9 android:id="@+id/imageButton" 10 android:layout_width="350dp" 11 android:layout_height="350dp" 12 android:layout_marginStart="1dp" 13 android:layout_marginTop="160dp" 14 android:layout_marginEnd="1dp" 15 android:layout_marginBottom="26dp" 16 android:background="#00000000" 17 android:scaleType="fitXY" 18 app:layout_constraintBottom_toTopOf="@+id/textView14" 19 app:layout_constraintEnd_toEndOf="parent" 20 app:layout_constraintStart_toStartOf="parent" 21 app:layout_constraintTop_toTopOf="parent" 22 app:srcCompat="@drawable/A" /> 23 24 <TextView 25 android:id="@+id/textView14" 26 android:layout_width="wrap_content" 27 android:layout_height="wrap_content" 28 android:layout_marginBottom="259dp" 29 android:gravity="center_horizontal" 30 android:text="No.1" 31 android:textSize="60dp" 32 android:textColor="#FFFFFF" 33 app:layout_constraintBottom_toBottomOf="parent" 34 app:layout_constraintEnd_toEndOf="parent" 35 app:layout_constraintStart_toStartOf="parent" 36 app:layout_constraintTop_toBottomOf="@+id/imageButton" /> 37 38 39</androidx.constraintlayout.widget.ConstraintLayout>

land\activity_main.xml

xml

1<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:app="http://schemas.android.com/apk/res-auto" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 tools:context=".MainActivity"> 7 8 <androidx.recyclerview.widget.RecyclerView 9 android:id="@+id/recyclerView" 10 android:layout_width="0dp" 11 android:layout_height="match_parent" 12 app:layout_constraintBottom_toBottomOf="parent" 13 app:layout_constraintEnd_toEndOf="parent" 14 app:layout_constraintStart_toStartOf="parent" 15 app:layout_constraintTop_toTopOf="parent" 16 tools:listitem="@layout/recycler_row" /> 17 18 <ImageButton 19 android:id="@+id/left_button" 20 android:layout_width="wrap_content" 21 android:layout_height="wrap_content" 22 android:layout_marginStart="67dp" 23 android:layout_marginBottom="63dp" 24 app:layout_constraintBottom_toBottomOf="parent" 25 app:layout_constraintStart_toStartOf="parent" 26 android:background="@null" 27 app:srcCompat="@drawable/arrow_left" /> 28 29 <ImageButton 30 android:id="@+id/right_button" 31 android:layout_width="wrap_content" 32 android:layout_height="wrap_content" 33 android:layout_marginEnd="67dp" 34 android:layout_marginBottom="63dp" 35 app:layout_constraintBottom_toBottomOf="parent" 36 app:layout_constraintEnd_toEndOf="parent" 37 android:background="@null" 38 app:srcCompat="@drawable/arrow_right" /> 39 40 41</androidx.constraintlayout.widget.ConstraintLayout>

試したこと

recyclerView.smoothScrollToPositionを使用し、「positionが2のとき、recyclerView.smoothScrollToPosition(3)」も試してみましたが、
要素の端を中心にしたことで、recyclerView.smoothScrollToPosition(6)へ移動するときにNo.6を飛ばしてNo.7へ移動してしまいました…

補足情報(FW/ツールのバージョンなど)

Android studioを使用し、javaで作成しています。
どうにか実現したい事ができないかインターネットで調べてみましたが、
全然実現方法がわかりませんでした…
お手数をおかけしますが、プログラミングも初心者のため丁寧に説明もいただけるとありがたいです。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

stackoverflow に
ボタンクリックでrecyclerviewの次のオブジェクトに移動するにはどうすればよいですか?
という記事がありました。

layoutManager.scrollToPosition() を使った場合の質問ですので回答もこのメソッドで書いてありますが、LayoutManager にはその smooth 版の smoothScrollToPosition() もありますので、それで書けます。

rLayoutManager 変数の型を RecyclerView.LayoutManager からLinearLayoutManager に変えて

java

1LinearLayoutManager rLayoutManager = new LinearLayoutManager()

各ボタンのリスナ(onClick)では

java

1left_button.setOnClickListener(new View.OnClickListener() { 2 @Override 3 public void onClick(View view) { 4 if (rLayoutManager.findFirstCompletelyVisibleItemPosition() > 0) { 5 rLayoutManager.smoothScrollToPosition(recyclerView, new RecyclerView.State(), 6 rLayoutManager.findFirstCompletelyVisibleItemPosition() - 1); 7 } 8 } 9}); 10 11right_button.setOnClickListener(new View.OnClickListener() { 12 @Override 13 public void onClick(View view) { 14 if (rLayoutManager.findLastCompletelyVisibleItemPosition() < (recyclerAdapter.getItemCount() - 1)) { 15 rLayoutManager.smoothScrollToPosition(recyclerView, new RecyclerView.State(), 16 rLayoutManager.findLastCompletelyVisibleItemPosition() + 1); 17 } 18 } 19});

としてみてください。


MainActivity に以下のメソッドを追加し

java

1 private int calcPixelFromDp(int dp){ 2 DisplayMetrics metrics = getResources().getDisplayMetrics(); 3 return (int)(dp * metrics.density); 4 }

各ボタンは以下のようにすると一応動作しました。
-200,200 のところは、それぞれ recycler_view のトップコンテナの width の値(450?)から負数(-450),正数(450)としてください。
こちらでは 200 でテストしたのでこの値となっています。

java

1 left_button.setOnClickListener(new View.OnClickListener() { 2 @Override 3 public void onClick(View view) { 4 recyclerView.smoothScrollBy(calcPixelFromDp(-200), 0); 5 } 6 }); 7 8 right_button.setOnClickListener(new View.OnClickListener() { 9 @Override 10 public void onClick(View view) { 11 recyclerView.smoothScrollBy(calcPixelFromDp(200), 0); 12 } 13 });

なお、smoothScrollBy を使うにしてもその値を自動で求められないかとやっていた時に、なぜか width=150 にすると No.1 と No.7 が中央に出来ない(しようとするとNo.2/No6に戻される)事象が出ました。
タッチ操作でも同様でしたのでボタン等の問題では無く LinearLayoutManager もしくは ItemDecoration 関係のようですが、今のところ問題点の想像もついていません。

投稿2021/11/04 18:39

編集2021/11/05 11:47
jimbe

総合スコア13209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

roatt

2021/11/05 04:39

ご回答ありがとうございます! 上記コードでやってみましたが、 ・left_buttonを押したときにNo.2→No.1に移動 ・right_buttonを押したときにNo.6→No.7に移動 はできましたが、それ以外のポジションでボタン押下した際、スクロール量が足りないのか少しスライドする動きをみせるだけで、もとの位置に戻ってしまいます…
jimbe

2021/11/05 05:55

前にお聞きしたかも知れませんが、タブレットのような広い画面でお使いでしょうか。 そうすると中央の行以外の行も画面内にほぼ(または完全に)表示された状態でしょうか。 回答のコードは、例えば左へのボタンを押したときは「一番左にある"完全に表示されている行"のもう1つ左の行を完全に表示する」という動きと思います。 そのため、左に"ほぼ表示"されている行があると僅かにスクロールするだけで表示されるため、センタリングの処理で元に戻されてしまうのかもしれません。 ポジションによるスクロールの指定では表示位置の指定に「中央に」というのが無さそうなので、別の方法が必要かもしれませんね。 帰宅してからまた考え直します。
roatt

2021/11/05 07:40

タブレットを使用しており、No.1、No.2、No.3は表示されている状態です… >そのため、左に"ほぼ表示"されている行があると僅かにスクロールするだけで表示されるため、センタリングの処理で元に戻されてしまうのかもしれません。 まさにその状況です。 すいません、毎回ありがとうございます…
roatt

2021/11/08 04:17

返信が遅くなってしまい、申し訳ありません。 修正したもので試したところ、ボタンでスクロールができるようになっておりました!! 本当にありがとうございました。
jimbe

2021/11/08 05:30

こちらのように端が戻ってしまう現象が無ければ、とりあえず良かったです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問