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

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

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

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

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

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

Q&A

解決済

1回答

2501閲覧

java.lang.NullPointerException Android studio

tetejiro

総合スコア17

Java

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

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

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

0グッド

0クリップ

投稿2024/01/22 14:12

編集2024/01/25 09:05

実現したいこと

カレンダーを基にしたアプリを作成しています。
現在は、初期表示として1月のカレンダーが表示されており(12月31日・2月1~10日も一緒に表示)
1月から2月もしくは12月に移動できる仕様です。

該当のソースコード

MonthFragment.java

1~~省略~~ 2public class MonthFragment extends Fragment { 3 View view; 4 Calendar this_month_instance; 5 int this_first_day_of_week; 6 Integer this_last_day_of_week; 7 int preMaxDate; 8 int rest; 9 10 private ArrayList<DateList> dateList; 11 Calendar cl = new GregorianCalendar(); 12 int this_year = cl.get(Calendar.YEAR); 13 int this_month = cl.get(Calendar.MONTH); 14 int this_date = cl.get(Calendar.DATE); 15 int this_maxDate = cl.getActualMaximum(Calendar.DATE); // 今月の最大日数 16 int idx = 0; 17 18 @Override 19 public View onCreateView(LayoutInflater inflater, ViewGroup container, 20 Bundle savedInstanceState) { 21 return inflater.inflate(R.layout.month_fragment, container, false); 22 } 23 24 @Override 25 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 26 super.onStart(); 27 this.view = view; 28 Button post = view.findViewById(R.id.post); 29 post.setOnClickListener(new View.OnClickListener() { 30 @Override 31 public void onClick(View view) { 32 this_month++; 33 viewCalendar(); 34 } 35 }); 36 viewCalendar(); 37 } 38 39 public void viewCalendar() { 40 dataInitialize(); 41 42 TextView yearText = this.view.findViewById(R.id.year); 43 yearText.setText(this_year + "年"); 44 45 TextView monthText = this.view.findViewById(R.id.month); 46 monthText.setText(this_month + 1 + "月"); 47 48 RecyclerView recyclerView = this.view.findViewById(R.id.date_recycler_view_container); 49 recyclerView.setHasFixedSize(true); 50 // ①recycleView に layoutManager をセット 51 recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 7)); 52 // ②Adapter を生成して RecyclerView にセット 53 recyclerView.setAdapter(new Monthly_RecyclerView_Adapter(getActivity(), this.dateList)); 54 } 55 56 // dateList = [DateList, , ...] を作成 57 private void dataInitialize() { 58 this.dateList = new ArrayList<>(); // push する対象 59 // 今月1日のインスタンス 60 this.this_month_instance = new GregorianCalendar(this.this_year, this.this_month, 1); 61 // 今月1日の曜日 62 this.this_first_day_of_week = this_month_instance.get(Calendar.DAY_OF_WEEK); 63 // 今月最終日の曜日 64 this.this_last_day_of_week = new GregorianCalendar(this.this_year, this.this_month, this.this_maxDate).get(Calendar.DAY_OF_WEEK); 65 // 先月の最大日数 66 this.preMaxDate = new GregorianCalendar(this.this_year, this.this_month-1, 1) 67 .getActualMaximum(Calendar.DATE); 68 69 //★① 1日よりも前の日付生成 70 this.this_first_day_of_week = - (this.this_first_day_of_week - 1); // -(今月初日の曜日 - 1) 71 if(this.this_first_day_of_week <= 0) { 72 //「1日の曜日-1」が付け足す先月の日数。その日数の絶対値をマイナスにして、カウントアップし、0未満の場合は繰り返す。 73 while(this.this_first_day_of_week < 0) { 74 this.dateList.add(new DateList(this.this_year, this.this_month - 1, this.preMaxDate+this.this_first_day_of_week+1, false)); 75 this.this_first_day_of_week++; 76 } 77 this.idx++; 78 } 79 //★② その月の日付生成 80 while(this.idx <= this.this_maxDate) { 81 // 当日は当日フラグ = true 82 if(this.idx == this.this_date) { 83 this.dateList.add(new DateList(this.this_year, this.this_month, this.idx, true)); 84 // 当日は当日フラグ = false 85 } else { 86 this.dateList.add(new DateList(this.this_year, this.this_month, this.idx, false)); 87 } 88 this.idx++; 89 } 90 //★③ 来月の日付生成 91 this.rest = 7 - this.this_last_day_of_week; 92 this.idx = 1; 93 // 先月の最終週の日数(rest) + 次の週の日数(7日) 94 while (rest+7 > 0) { 95 this.dateList.add(new DateList(this.this_year, this.this_month + 1, this.idx, false)); 96 this.idx++; 97 this.rest--; 98 } 99 } 100 public class DateList { 101 private int year; // 年 102 private int month;// 月 103 private int date; // 日にち 104 private boolean todayFlg; // 今日かどうかのフラグ 105 DateList(int year,int month, int date, boolean todayFlg) { 106 this.year = year; 107 this.month = month; 108 this.date = date; 109 this.todayFlg = todayFlg; 110 } 111 public int getYear() { 112 return this.year; 113 } 114 public int getMonth() { 115 return this.month; 116 } 117 public int getDate() { 118 return this.date; 119 } 120 } 121}

Monthly_RecyclerView_Adapter.java

1~~省略~~ 2public class Monthly_RecyclerView_Adapter extends RecyclerView.Adapter<Monthly_RecyclerView_Adapter.ViewHolder>{ 3 4 Context content; 5 ArrayList<MonthFragment.DateList> DateList; 6 7 Monthly_RecyclerView_Adapter(Context content, ArrayList<MonthFragment.DateList> DateList) { 8 this.content = content; 9 this.DateList = DateList; 10 } 11 12 @Override 13 public int getItemCount() { 14 return this.DateList.size(); 15 } 16 17 @NonNull 18 @Override 19 public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 20 // content は MainActivity 21 View view = LayoutInflater.from(content).inflate(R.layout.date_viewholder, parent, false); 22 return new ViewHolder(view); 23 } 24 25 @Override 26 public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 27 28 // 各日付の曜日を取得 29 int year = this.DateList.get(position).getYear(); 30 int month = this.DateList.get(position).getMonth(); 31 int date = this.DateList.get(position).getDate(); 32 33 Calendar cl = new GregorianCalendar(year, month, date); 34 int dayOfWeekNum = cl.get(Calendar.DAY_OF_WEEK); 35 36 String[] weekDays = {"", "(日)", "(月)", "(火)", "(水)", "(木)", "(金)", "(土)"}; 37 String dayOfWeek = weekDays[dayOfWeekNum]; 38 39 // 日付 + 曜日を出力 40 holder.dateBox.setText(date + dayOfWeek); 41 42 holder.dateBox.setClickable(true); 43 holder.dateBox.setOnClickListener(new View.OnClickListener() { 44 @Override 45 public void onClick(View view) { 46 TextView textView = (TextView)view; 47 FragmentActivity fragmentActivity = (FragmentActivity)view.getContext(); 48 DateFragment dateFragment = new DateFragment(); 49 DailyCalendarFragment dailyCalendarFragment = new DailyCalendarFragment(); 50 51 // 日付画面フラグメントにパラメータを付与する(〇月・〇日) 52 Bundle bundle = new Bundle(); 53 TextView monthView = fragmentActivity.findViewById(R.id.month); 54 bundle.putString("month", monthView.getText().toString()); 55 bundle.putString("date", textView.getText().toString()); 56 dateFragment.setArguments(bundle); 57 58 // 日付画面フラグメントを起動する 59 fragmentActivity.getSupportFragmentManager() 60 .beginTransaction() 61 .replace(R.id.month_fragment_container, dateFragment) 62 .addToBackStack("date") 63 .commit(); 64 65 fragmentActivity.getSupportFragmentManager() 66 .beginTransaction() 67 .add(R.id.fragmentContainerView, dailyCalendarFragment) 68 .addToBackStack("dailyCalender") 69 .commit(); 70 } 71 }); 72 } 73 74 public static class ViewHolder extends RecyclerView.ViewHolder { 75 TextView dateBox; 76 77 ViewHolder(@NonNull View itemView) { 78 super(itemView); 79 dateBox = itemView.findViewById(R.id.every_date); 80 } 81 } 82}

MainActivity.java

1package com.example.RecordTime; 2~~省略~~ 3public class MainActivity extends FragmentActivity { 4 @Override 5 protected void onCreate(Bundle savedInstanceState) { 6 super.onCreate(savedInstanceState); 7 setContentView(R.layout.activity_main); 8 9 getSupportFragmentManager().beginTransaction() 10 .setReorderingAllowed(true) 11 .add(R.id.month_fragment_container, new MonthFragment()) 12 .commit(); 13 } 14}

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

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

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

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

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

jimbe

2024/01/22 15:58 編集

エラーのスタックトレースの中に、MonthFragment.java:xx とか MainActivity.java:xx とかご自身で作ったプログラムと行番号の個所が幾つかあったはずです。 それはどのファイルのどの行だったでしょうか。 Monthly_RecyclerView_Adapter クラスが無いと動作確認出来ません。 なんとか載せて頂けませんでしょうか。
guest

回答1

0

ベストアンサー

MainActivity.java(一部)

java

1 MonthFragment monthFragment = new MonthFragment(); 2() 3 // 月画面フラグメントを表示 4 getSupportFragmentManager().beginTransaction() 5 .setReorderingAllowed(true)//トランザクションに関与するフラグメントの状態変更を最適化 6 .add(R.id.month_fragment_container, new MonthFragment()) 7 .commit(); 8() 9 public void plus(View view) { 10 monthFragment.plus(); 11 }

これでは、 plus を実行するフラグメントオブジェクトと画面に表示しているフラグメントオブジェクトは 違うモノ です。
View は Activity に載せないと onCreateView や onViewCreated 等のライフサイクルメソッドは呼ばれません。 従って this.activity も null のままですので、 viewCalendar() 内の activity.findViewById() で例外になっています。

.add(R.id.month_fragment_container, monthFragment)

としなければならないでしょう。


動作確認しようとコードをコピペして見ていますが…フラグメントのレイアウトなのに
アクティビティで findViewById しています。(activity.findViewById(R.id.year);)
フラグメントの onViewCreated の第一パラメータ view が onCreateView が返した View そのものですので、そのビューから findViewById で得なければならないでしょう。(view.findViewById(R.id.year);)

アクティビティにアタッチしていればビュー階層的にはアクティビティにも属している形になるのでこれでも動くようですが、本来フラグメントはそれ単体で完結するものです。ボタンのクリック処理もフラグメントに書くべきです。


アダプタが分かりませんが想像で追加、フラグメントで完結するようにしました。
Calendar は扱い難いので LocalDate/YearMonth に変更、年月の表示は Adapter の更新を受ける形とし、年月の国際化対応(?)、曜日名表示の追加、今日の日は描画時に背景色を変えています。

MainActivity.java

java

1import android.os.Bundle; 2 3import androidx.appcompat.app.AppCompatActivity; 4 5public class MainActivity extends AppCompatActivity { 6 @Override 7 protected void onCreate(Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 setContentView(R.layout.activity_main); 10 11 if(savedInstanceState == null) { 12 getSupportFragmentManager().beginTransaction() 13 .replace(R.id.fragment_container, new MonthFragment()) 14 .commit(); 15 } 16 } 17}

res/layout/activity_main.xml

xml

1<?xml version="1.0" encoding="utf-8"?> 2<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:id="@+id/fragment_container" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" 7 tools:context=".MainActivity" />

MonthFragment.java

java

1import android.graphics.Color; 2import android.os.Bundle; 3import android.text.format.DateUtils; 4import android.view.*; 5import android.widget.*; 6 7import androidx.annotation.*; 8import androidx.fragment.app.*; 9import androidx.recyclerview.widget.*; 10 11import java.time.*; 12import java.time.format.TextStyle; 13import java.time.temporal.*; 14import java.util.*; 15import java.util.function.Consumer; 16 17public class MonthFragment extends Fragment { 18 public MonthFragment() { 19 super(R.layout.month_fragment); 20 } 21 22 @Override 23 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 24 TextView monthText = view.findViewById(R.id.month); 25 26 Adapter adapter = new Adapter(yearMonth -> { 27 long millies = yearMonth.atDay(1).getLong(ChronoField.EPOCH_DAY) * 24 * 60 * 60 * 1000; //epoch[ms] 28 monthText.setText(DateUtils.formatDateTime(requireContext(), millies, DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_NO_MONTH_DAY)); 29 }); 30 31 Button prevButton = view.findViewById(R.id.prev); 32 prevButton.setOnClickListener(v -> adapter.prev()); 33 34 Button nextButton = view.findViewById(R.id.next); 35 nextButton.setOnClickListener(v -> adapter.next()); 36 37 RecyclerView recyclerView = view.findViewById(R.id.recycler_view); 38 recyclerView.setHasFixedSize(true); 39 recyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 7)); 40 recyclerView.setAdapter(adapter); 41 } 42 43 private static class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> { 44 private final DayOfWeek firstDayOfWeek = WeekFields.of(Locale.getDefault()).getFirstDayOfWeek(); //週の始まり 45 46 private final Consumer<YearMonth> dateChangeListener; 47 48 private YearMonth current; 49 private LocalDate start; 50 51 Adapter(@NonNull Consumer<YearMonth> dateChangeListener) { 52 this.dateChangeListener = dateChangeListener; 53 54 setYearMonth(YearMonth.now()); 55 } 56 57 void next() { 58 setYearMonth(current.plusMonths(1)); 59 } 60 61 void prev() { 62 setYearMonth(current.minusMonths(1)); 63 } 64 65 private void setYearMonth(YearMonth yearMonth) { 66 this.current = yearMonth; 67 start = current.atDay(1).with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); //月初直前の週始め 68 notifyItemRangeChanged(7, 6*7); //日付部分 69 if(dateChangeListener != null) dateChangeListener.accept(current); 70 } 71 72 @NonNull 73 @Override 74 public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 75 return new ViewHolder(parent); 76 } 77 78 @Override 79 public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 80 holder.bind(position); 81 } 82 83 @Override 84 public int getItemCount() { 85 return 7 + 6*7; 86 } 87 88 class ViewHolder extends RecyclerView.ViewHolder { 89 private final int HEADER_BGCOLOR = Color.rgb(240,240,240); 90 private final TextView day; 91 ViewHolder(ViewGroup parent) { 92 super(LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_day, parent, false)); 93 day = itemView.findViewById(R.id.day); 94 } 95 void bind(int position) { 96 if(position < 7) { //曜日名 97 DayOfWeek dow = firstDayOfWeek.plus(position); 98 day.setTextColor(getTextColor(dow)); 99 day.setBackgroundColor(HEADER_BGCOLOR); 100 day.setText(dow.getDisplayName(TextStyle.SHORT_STANDALONE, Locale.getDefault())); 101 } else { 102 LocalDate date = start.plusDays(position - 7); 103 day.setTextColor(getTextColor(date)); 104 day.setBackgroundColor(getBackgroundColor(date)); 105 day.setText(String.valueOf(date.getDayOfMonth())); 106 } 107 } 108 private int getTextColor(LocalDate date) { 109 return date.getMonth() != current.getMonth() ? Color.LTGRAY : //前月・次月 110 getTextColor(date.getDayOfWeek()); 111 } 112 private int getTextColor(DayOfWeek dayOfWeek) { 113 return dayOfWeek == DayOfWeek.SUNDAY ? Color.RED : //日曜 114 dayOfWeek == DayOfWeek.SATURDAY ? Color.BLUE : //土曜 115 Color.BLACK; 116 } 117 private int getBackgroundColor(LocalDate date) { 118 return date.isEqual(LocalDate.now()) ? Color.CYAN : //今日 119 Color.TRANSPARENT; 120 } 121 } 122 } 123}

res/layout/month_fragment.xml

xml

1<?xml version="1.0" encoding="utf-8"?> 2<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent"> 6 7 <Button 8 android:id="@+id/prev" 9 style="?android:attr/borderlessButtonStyle" 10 android:layout_width="wrap_content" 11 android:layout_height="wrap_content" 12 android:backgroundTint="@color/white" 13 android:text="prev" 14 android:textColor="@color/black" 15 android:textSize="24sp" 16 app:layout_constraintBaseline_toBaselineOf="@id/month" 17 app:layout_constraintStart_toStartOf="parent" /> 18 19 <TextView 20 android:id="@+id/month" 21 android:layout_width="0dp" 22 android:layout_height="wrap_content" 23 android:layout_marginTop="32dp" 24 android:text="month" 25 android:textAlignment="center" 26 android:textSize="24sp" 27 app:layout_constraintEnd_toEndOf="parent" 28 app:layout_constraintStart_toStartOf="parent" 29 app:layout_constraintTop_toTopOf="parent" /> 30 31 <Button 32 android:id="@+id/next" 33 style="?android:attr/borderlessButtonStyle" 34 android:layout_width="wrap_content" 35 android:layout_height="wrap_content" 36 android:backgroundTint="@color/white" 37 android:text="next" 38 android:textColor="@color/black" 39 android:textSize="24sp" 40 app:layout_constraintBaseline_toBaselineOf="@id/month" 41 app:layout_constraintEnd_toEndOf="parent" /> 42 43 <androidx.recyclerview.widget.RecyclerView 44 android:id="@+id/recycler_view" 45 android:layout_width="0dp" 46 android:layout_height="wrap_content" 47 app:layout_constraintBottom_toBottomOf="parent" 48 app:layout_constraintEnd_toEndOf="parent" 49 app:layout_constraintStart_toStartOf="parent" 50 app:layout_constraintTop_toBottomOf="@id/month" /> 51 52</androidx.constraintlayout.widget.ConstraintLayout>

res/layout/grid_day.xml

xml

1<?xml version="1.0" encoding="utf-8"?> 2<TextView xmlns:android="http://schemas.android.com/apk/res/android" 3 android:id="@+id/day" 4 android:layout_width="match_parent" 5 android:layout_height="wrap_content" 6 android:autoSizeTextType="uniform" 7 android:ellipsize="end" 8 android:maxLines="1" 9 android:text="21" 10 android:textAlignment="center" 11 android:textSize="30sp" />

起動時(1月)スクリーンショット
next押下時(2月)スクリーンショット

投稿2024/01/22 15:24

編集2024/01/25 10:21
jimbe

総合スコア13209

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

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

tetejiro

2024/01/25 09:40

リアクションが遅くなってしまい、大変申し訳ございません。 前回の質問同様に、ご丁寧に回答をしていただきましてありがとうございます。 (https://teratail.com/questions/nq6yuripcws7qn) いただきましたコード(アダプタが分かりませんが想像で追加~)に関してですが、 そのままコピペして試そうとしたのですが そのままではなぜかエラーがでるようで ひとまずは時間がかかると思いますが、自分で読んでみている状況です。 コメントにてコードの質問をさせていただくかもしれません。 もしお時間がありましたら、是非ご回答をお願いいたします。 また、ご指摘いただいた以下の点を修正しましたところ、 エラー自体は出なくなりました。(日付が不正確に出てしまっているため完全ではない状況です。) ありがとうございます。 ①plus を実行するフラグメントオブジェクトと画面に表示しているフラグメントオブジェクトは 違うモノ です。 ②フラグメントの onViewCreated の第一パラメータ view が onCreateView が返した View そのものですので、そのビューから findViewById で得なければならないでしょう。 ですが、いただいているコードの方がやはり良いと思いますので まずは読んだ上で、取り入れていきたいと思います。 改めまして、ご回答ありがとうございました。
jimbe

2024/01/25 10:22 編集

>そのままコピペして試そうとしたのですが >そのままではなぜかエラーがでるようで 今の最新でこちらではエラーになっていません。回答を書いて以降も試しながらちみちみと回答のコードを更新していましたので、もし途中の状態でコピペされていましたら不具合があるかもしれませんので、今の最新でコピペしてみてください。 また、それでも何かエラー等出るようでしたら、このコメント欄に書いて頂いて結構です(質問に編集追記しては質問自体との関連が分かり難いですし、回答は私しか編集出来ませんので…)。 >日付が不正確に出てしまっている こちらでも発生していました。dataInitialize での計算の部分で MonthFragment のフィールド(this_~) の一部が再計算されていなかったためと思います。 そもそも随時計算するのですからフィールドで持っている必要が無いものまで持ってしまっていたために間違え易かったのではないでしょうか。 すいません、今ちょっとまた直してしまいました (_ _;
jimbe

2024/01/26 09:41

アダプタ追記して頂いてたんですね、気付かずすいません。 日付のクリック処理があった方が良いでしょうか。 MainActivity では MonthFragment しか書いていませんが、アクティビティのレイアウトにはフラグメントを置く view が二つあるんですかね。
tetejiro

2024/01/26 18:05 編集

気にかけていただいてありがとうございます。 〇現状の状況として、 コードをコピペしたところ、通りまして、想定通りの動作をしていました。 ありがとうございます。 〇>dataInitialize での計算の部分で再計算されていなかったためと思います。 コードを読んでいて、やはり設計の部分がよくないという事が分かりました。 やはりいただいたコードにより、全面的に設計を直そうと思います。 〇>日付のクリック処理があった方が良いでしょうか。 要件として、そのような機能を想定しております。 自分でやってみて分からなかった場合、また質問をさせていただいてよろしいでしょうか? わざわざありがとうございます。 〇>MainActivity では MonthFragment しか書いていませんが、アクティビティのレイアウトにはフラグメントを置く view が二つあるんですかね。 具体的にどこのことを指しておっしゃっているのか イメージが湧いておらず、、、すみません。 コード全文が載っていないのがよくないと思いまして、 GitHubに全コードを載せているためご紹介させていただきます。 https://github.com/tetemalu/Record-Time ※私が書いたコードを上げました。 また、私の想定している要件としましては ・カレンダーの日付をタップすると、 ・その日の詳細ページに遷移し、 ・その日に登録してある情報を閲覧できる ・また、その日の情報を登録することができる という機能が含まれているアプリケーションです。 このような機能が含まれていることと、アクティビティを 出来る限り1つに絞り、フラグメントの加減により実装しようとしているため 頻繁にフラグメントを載せたりすることを想定しています。 〇今読めているところまでなのですが 質問をさせていただいてもよろしいでしょうか? ①Adapter adapter = new Adapter(yearMonth -> { ~省略~ } この引数の yearMonth の定義がないように思っていて、 この変数がどこからきているのか分からないです。 ②アダプタのコンストラクタの部分に関してです。 public Adapter(@NonNull Consumer<YearMonth> dateChangeListener) { this.dateChangeListener = dateChangeListener; setYearMonth(YearMonth.now()); } ①で引数で yearMonth を引数で渡しているものの コンストラクタ側では yearMonth を受け取っていないと思うのですが、 定義では引数は Consumer<YearMonth> dateChangeListener となっていて どうしてかみ合うのかが分からないです。 ③①の yearMonth と ②のコンストラクタの中身の YearMonth.now() の YearMonth は、大文字と小文字を区別するという Java の特性上 異なるものと考えてよろしいのでしょうか? 毎回長々となってすみません。 もしお時間がありましたらご回答をお願いいたします。
jimbe

2024/01/27 05:05 編集

動作して取り合えず一安心です。 計算の部分は変数が多いのでその分名前も長くなりますし、メソッド内の変数だけでなくフィールドの変数もあると、ごちゃごちゃしてしまいます。 計算の部分々々をメソッドに分けて一度に現れる変数を減らすような工夫も必要でしょうね。 回答のコードでは、表示の一番最初の日付だけを求めて後は随時 LocalDate の日付の加算 ( start.plus(~) )で済ませることにしました。月替わり・年替わりも処理してくれますのでただ何日目かだけで済みます。 日付のクリック時の処理は ViewHolder 内で TextView に登録するのは合っていますが、FragmentManager を使うに当たり Context を Activity と見なして使う ( (FragmentActivity)view.getContext() ) のは、回答に書いたようにフラグメントの独立性に関わります。フラグメントは TextView のように再利用できる部品としての性格もありますので(実際に MonthFrament を再利用するかどうかはともかく) フラグメントの親がアクティビティとは限りません(フラグメントはフラグメントにも載せられます) から、その辺りも上手く処理できると良いと思います。 フラグメントが二つというのは、そのクリック処理として(ViewHolder の dateBox に設定している onClick(View view) メソッド内で) フラグメントマネージャを用いて DateFragment と DailyCalendarFragment を設定していますね、そのことです。 GitHub 、後ほど拝見します。 Adapter のコンストラクタに書いているモノのことですが、これは "ラムダ式" という書き方をした無名クラスです。 これは先の日付のクリック処理で書くような holder.dateBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { : } }); と(ほぼ)同じことをもっと簡単に書くようなもので、 "->" の右が処理、左が処理が受け取るパラメータ変数になります。 上のクリックの書き方をラムダ式に変えると holder.dateBox.setOnClickListener(view -> { : }); となります。 "->" の左にある view は onClick(View view) の引数の変数名です。 "{}" も一組減ってますし、むちゃくちゃ短くなりますよね。 Adapter のコンストラクトの所以外でも prevButton 等で prevButton.setOnClickListener(v -> adapter.prev()); としている 『v -> adapter.prev()』 も ラムダ式で書いた OnClickListener で、普通に無名クラスで書くと new View.OnClickListener() { @Override public void onClick(View v) { adapter.prev(); } } となるところが setOnClickListener も含めて一行で収まります。(処理部分が一行な場合は処理を囲む {} と行終端の ; も省略出来るのです。) つまり Adapter のコンストラクタのパラメータとして、該当処理をする無名クラス(のオブジェクト)を渡しているのです。 そして OnClickListener は onClick が呼ばれるメソッドですが、 Consumer は accept がメソッドになります。 なので dateChangeListener を使っている setYearMonth メソッドでは "dateChangeListener.accept(current)" として、 Adapter のコンストラクタで渡された無名クラスの処理を current を パラメータとして呼び出しています。 で、これは全て Consumer<YearMonth> 型である dateChangeListener (の内部)の定義の話です。 setYearMonth メソッドを呼んでいるパラメータ部分は YearMonth クラスの now () メソッドを呼んでいるだけで、無名クラスとは関係ありません。
jimbe

2024/01/26 19:58 編集

GitHub のコードから MainActivity/MonthFragment/DateFragment を修正してみました。 https://github.com/Jimbe-github/tetemalu_RecordTime なお、 GitHub のコードに対する質問をここで展開してしまうと他の人には良く分からないことになりかねませんので、 GitHub を見なくても分かるような、ここに書ける範囲でお願いします^^;
tetejiro

2024/02/13 20:03 編集

また遅くなってしまい、大変申し訳ございません。 質問にご回答いただきましてありがとうございました。 まだ書き方に慣れないのですが、 ご丁寧に回答いただけたのでなんとか理解ができたと思います。 Adapter adapter = new Adapter(yearMonth -> {} の yearMonth の実態は Adapter クラス内の private final Consumer<YearMonth> dateChangeListener; であると理解しました。 また分からないことが出てきた場合は、質問をさせていただくかもしれません。 ※追記 ↑認識間違っていたことに気が付きました。 無名クラスでかかない場合、以下であり、この new した Consumer<YearMonth> を 引数としていると理解しました。解説いただいていたのに理解できておらずすみませんでした。 Adapter adapter = new Adapter(new Consumer<YearMonth>() { @Override public void accept(YearMonth yearMonth) { // 〇年 TextView year_text = view.findViewById(R.id.year); year_text.setText(String.valueOf(yearMonth.getYear()) + "年"); // 〇月 TextView month_text = view.findViewById(R.id.month); month_text.setText(String.valueOf(yearMonth.getMonthValue()) + "月"); } }); >GitHub を見なくても分かるような、ここに書ける範囲でお願いします 承知しました。ご指摘ありがとうございます。 文字数制限が厳しいのですができるだけ工夫して収めて質問をしていきます。 GitHubのコードも今拝見しております。 コードの改善点が知れて大変勉強になっております。 所用で時間がなかなか取れないでいるのですが 必ず読んで完成させたいと思います。 完成までまだまだかかると思うので、 また質問をさせていただくことになると思います。 その時はまたお付き合いいただけますと幸いです。 毎回ご丁寧に回答いただき大変ありがたい限りです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問