そうだ、Android アプリを作ろう~実験編~Navigationで画面遷移を作る
前回の記事(そうだ、Android アプリを作ろう~実験編~新しい画面を作る)で新しい画面の見た目を作った。今回はこれを表示させる制御を作っていきたい。ソースコードをたくさん引用したせいで記事が長くなってしまったけど、ぜひぜひ最後までお付き合いくださいませ~。
nav_graph.xmlを変更する(遷移ルールの追加と変更)
まずは、ソースコードのどこに手をくわえればよいか見定める必要がある。前回も登場した画面遷移のルールを司るnav_graph.xmlは必須だろう。
<fragment
android:id="@+id/FirstFragment"
android:name="com.example.myapplication.FirstFragment"
android:label="@string/first_fragment_label"
tools:layout="@layout/fragment_first">
<action
android:id="@+id/action_FirstFragment_to_SecondFragment"
app:destination="@id/SecondFragment" />
</fragment>
<fragment
android:id="@+id/SecondFragment"
android:name="com.example.myapplication.SecondFragment"
android:label="@string/second_fragment_label"
tools:layout="@layout/fragment_second">
<action
android:id="@+id/action_SecondFragment_to_FirstFragment"
app:destination="@id/FirstFragment" />
</fragment>
上記の記述でFirstFragmentとSecondFragmentを行きつ戻りつするアクションを定義しているようだ。今回はSecondFragmentからSakuranoFragment(私が作った新しいフラグメント。自分の名前を主張する自我の強いタイプ)へ遷移させてみたいと思う。FirstFragmentもSecondFragmentほぼ同じことがかかれたあるので、コピペしてFirstもしくはSecondの部分をSakuranoに置換すればイケそうな気がする。
<fragment
android:id="@+id/SecondFragment"
android:name="com.example.myapplication.SecondFragment"
android:label="@string/second_fragment_label"
tools:layout="@layout/fragment_second">
<action
android:id="@+id/action_SecondFragment_to_SakuranoFragment"
app:destination="@id/SakuranoFragment" />
</fragment>
<fragment
android:id="@+id/SakuranoFragment"
android:name="com.example.myapplication.SakuranoFragment"
android:label="@string/sakurano_fragment_label"
tools:layout="@layout/fragment_sakurano">
<action
android:id="@+id/action_SakuranoFragment_to_FirstFragment"
app:destination="@id/FirstFragment" />
</fragment>
というわけで、新規のコードをSecondFragmentの後ろに追加してみた。SakuranoFragmentの次はFirstFragmentに遷移するようにしてみた。ちなみに、SecondFragmentのaction部分も action_SecondFragment_to_SakuranoFragment と変更している。
fragment_sakurano.xmlを変更する(新規画面の作成)
前回、fragment_second.xmlをコピペして作った新規ファイルに画像を埋め込んだ。今回は更に手を加えたい。fragment_sakurano.xmlに登場するsecondの文字をsakuranoに置換していく。SecondはSakuranoへ置換する(大文字と小文字に注意)。このとき、Ctrl+Rで画面左上に置換用ウィンドウが表示されるので活用してみて欲しい。
ちなみに、「Cc」というボタンは「大文字と小文字を区別する」。「W」は「単語単位で検索する(画像の場合、Secondという単語の前後に別の文字が付いていたらヒットしない)」だ。この2つはよく使うので覚えておいて欲しい。ちなみに、今回は大文字と小文字は区別したいので、さっそく「Cc」のボタンを活用しよう。もともと大文字の箇所を間違えて小文字に置換しないように。後々ビルドが通らない原因になるので、ダメ絶対!
strings.xmlを変更する(足りない定義の追加)
さて、nav_grach.xmlとfragment_sakurano.xmlの中身を変更すると、エラーを警告するために赤く色づいた行があったと思う。nav_grach.xmlでは以下の行で、
android:label="@string/sakurano_fragment_label"
fragment_sakurano.xmlでは以下の行だ。
android:text="@string/hello_sakurano_fragment"
これらの行はsakurano_fragment_labelもしくはhello_sakurano_fragmentというアイテムを参照しているが、それが無いためエラーとなっている。そのため、その定義を追加する必要がある。
置換前のsecond_fragment_labelもしくはhello_second_fragmentで検索すると、string.xmlにその定義があった。
<resources>
<string name="app_name">My Application</string>
<string name="action_settings">Settings</string>
<!-- Strings used for fragments for navigation -->
<string name="first_fragment_label">First Fragment</string>
<string name="second_fragment_label">Second Fragment</string>
<string name="next">Next</string>
<string name="previous">Previous</string>
<string name="hello_first_fragment">Hello first fragment</string>
<string name="hello_second_fragment">Hello second fragment</string>
</resources>
string name= の後ろにある second_fragment_label という定義にSecond Fragmentという文字列が関連付けられているという構成だ。hello_second_fragmentの方も同じで、実際に表示されるのはタグで囲われたHello second fragmentの方となる。さっそく足りない以下の定義を追加した。
<string name="sakurano_fragment_label">Sakurano Fragment</string>
<string name="hello_sakurano_fragment">Hello sakurano fragment</string>
SecondFragment.javaを変更する(既存画面の遷移先の変更)
SecondFragment.javaにはボタンを押下されたときの遷移先に関するアクションが記載されている。
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.e(TAG, "onViewCreated() call");
binding.buttonSecond.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.e(TAG, "onClick() call");
NavHostFragment.findNavController(SecondFragment.this)
.navigate(R.id.action_SecondFragment_to_FirstFragment);
}
});
}
R.id.action_SecondFragment_to_FirstFragmentの部分がそれにあたる。しかし、この定義はもう消してしまったため存在しない。これをaction_SecondFragment_to_SakuranoFragmentに変更した。
SakuranoFragment.javaを変更する(新規画面の作成2)
前回、FirstFragment.javaをコピーしてSauranoFragment.javaを作成した。そうすると、以下のような内容になっている。
import com.example.myapplication.databinding.FragmentFirstBinding;
public class SakuranoFragment extends Fragment {
private FragmentFirstBinding binding;
private final String TAG ="debug:Fragment:FirstFragment";
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
Log.e(TAG, "onCreateView() call");
binding = FragmentFirstBinding.inflate(inflater, container, false);
return binding.getRoot();
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.e(TAG, "onViewCreated() call");
binding.buttonFirst.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.e(TAG, "onClick() call");
NavHostFragment.findNavController(SakuranoFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);
}
});
}
こちらもFirstの部分をSakuranoにコツコツ置換していく。
R.id.action_FirstFragment_to_SecondFragment の部分だけはaction_SakuranoFragment_to_FirstFragmentに置き換えよう。
できあがりを確認しよう
ここまですると、nav_graph.xmlのDesigh画面は以下のようになった(実際は、javaのファイルを触らなくてもDesigh画面はこうなるけど)。
早速、ビルドして画面を確認してみる。FirstFragment画面から順番にボタンを押していくと……
SecondFragment画面のボタンがPREVIOUSとなっている箇所が違和感があるものの(前画面に戻るわけではないのでPREVIOUSはミスマッチ)、そのボタンを押すと――
新しい画面が表示された。やったね!
おまけ:PREVIOUSボタンを変更する(ダイジェストでお届けします)
せっかくなので、previousボタンはnextに変更しよう。今まで紹介した内容を駆使すればできるので、ダイジェストでお届けします。
previousで検索すると、second_fragment.xmlに使用箇所があり、
文言の定義はやはりstring.xmlにあった。
この部分をNextに変えても変更できるが、string name="previous" と文字列Next の意味がちぐはぐになってしまい、あまり宜しくない。
そこで、second_fragment.xmlを変えたい。下記のようになっているコードの android:text 箇所を
<Button
android:id="@+id/button_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/previous"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textview_second" />
下記のように変更すれば NEXT 表示になる。
android:text="@string/next"
おまけに(ドロイド君を表示する)
当初の目標はドロイド君を表示させる、だったので、今回使用した画像をドロイド君のものに置き換えると、以下のような表示となった。これで目標は達成できた。FirstFragmentもしくはSecondFragmentに画像を入れればもっと楽やったやないか~いとお嘆きの方もいるかもしれないが、そこはまぁNavigationへの理解が深まったので堪忍ということで。
ここまで駆け足でソースコードを変更した。置換で済ませたxmlファイルの中身など、まだまだ分からない部分もある。しかし、次回以降も手を動かすことで理解を深めていきたいと思う。