概要
読書に特化したアプリケーションを作成しています。
機能
登録、閲覧、削除、更新の機能を実装したいと考えています。現在完了しているのは閲覧、削除です。
https://jamboard.google.com/d/1Z7IRT7GP2ROn3AlAZVQAdSLEE5osza84ZYLpopTPV0M/edit?usp=sharing
動作確認
読書アプリの作成 pic.twitter.com/roDyYZXCoJ
— いまむら たくま (@Imamuuu5) May 19, 2023
読書アプリの作成2 pic.twitter.com/g3bWWdCVJB
— いまむら たくま (@Imamuuu5) May 19, 2023
java
MainActivity.java
package com.example.app19;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import android.content.Intent;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
public static final String EXTRA_PAN = BuildConfig.APPLICATION_ID + ".PAN"; // 本情報を送るときに使用するEXTRA名用定数
private List<book> bookList; // BOOK(データ)
private RecyclerView recycler; // リサイクラービュー
private book.Adapter adapter; // アダプター
public static final String EXTRA_TITLE = BuildConfig.APPLICATION_ID + ".TITLE"; // Extraに使う用の定数を用意
public static final String EXTRA_WHY01 = BuildConfig.APPLICATION_ID + ".WHY01"; // Extraに使う用の定数を用意
private ActivityResultLauncher<Intent> settingLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() { // 2つ目の引数で結果を受け取った時の処理(インタフェースを定義)
@Override
public void onActivityResult(ActivityResult result) {
if(result.getResultCode() == RESULT_OK) { // 結果がRESULT_OK(成功)の場合
Intent intent = result.getData(); // result.getData()により結果のインテント取得
p2_title = intent.getStringExtra(EXTRA_TITLE); // intentから上で定義したEXTRA_NAME(com.example.app14.NAME)という名前のデータをStringで取得
p2_why01 = intent.getStringExtra(EXTRA_WHY01);
}
}
}
);
int p2_num;
private String p2_title;
private String p2_why01;
private String p2_why02;
private String p2_why03;
private String p2_about;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bookList = new ArrayList<>(); // BOOKリストを初期化
//単語帳機能・・学習した単語を登録しテストできる機能(記憶の定着を高めるため一日、1週間、1か月のスパンでテストする)
book p1 = new book (R.drawable.book, 1," 読書方法", " 効果的な読書の仕方をしりたっかた", " 本の読み方ノウハウを知りたいから", "今後、積極的に本を読むようになりたいまた人生の幸福度を上げたい", " 目次 \n" +
"本を読む前の準備 \n" +
" ・内容を予測する(間違っても大丈夫)\n" +
" ・同じジャンルの本を複数読む(共通点がわかる) \n" +
" ・内容を予測する(間違っても大丈夫) \n" +
"読書中に意識すること \n" +
" ・読みたい章から読むこと \n" +
" ・すべてを読むのではなく、「しかし」「つまり」文の終わりつまり筆者が言いたいことを重点的に読む(全体の20%) \n" +
" ・内容に質問しながら読む(例)なぜ筆者はそう思ったのか?言いたいことは何なのか? \n" +
" ・一旦本を閉じ学習した内容をまとめる \n" +
" ・知っている内容と知らない内容の差を意識する \n" +
" ・要約しながら読む(予測とのギャップを意識) \n" +
"読み終えた時にすること(アウトプット) \n" +
" ・忘れている事を思い出す訓練 \n" +
" ・人に説明する \n" +
" ・学んだ事を体を使って実践してみる \n" +
" 違う方法で三回アウトプットしてみる");
p2_num=2;
p2_title="";
p2_why01="";
p2_why02="";
p2_why03="";
p2_about="";
book p2 = new book (R.drawable.book,p2_num,p2_title, p2_why01, p2_why02, p2_why03, p2_about);
// 追加機能の編集
bookList.add(p1);
bookList.add(p2);
recycler = findViewById(R.id.recycler);
recycler.setLayoutManager(new LinearLayoutManager(this)); // リストの表示形式を縦並びに設定
adapter = new book.Adapter( bookList ); // 本リストを基にアダプターを生成
recycler.setAdapter(adapter); // リサイクラーにアダプターをセット
//
findViewById(R.id.new_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, NewAdd.class); // RegisterActivityを作っていない場合エラー
startActivity(intent);
}
});
}
}
book.java
package com.example.app19;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class book implements Parcelable {
private int imageRes; // 本のイメージリソース
private int num; // 番号
private String title; // 自作タイトル
private String why01; // 事前準備1
private String why02; // 事前準備2
private String why03; // 事前準備3
private String about; // 内容
//本情報初期化用コンストラクタ
book(int imageRes, int num, String title, String why01, String why02, String why03, String about) {
this.imageRes = imageRes;
this.num = num;
this.title = title;
this.why01 = why01;
this.why02 = why02;
this.why03 = why03;
this.about = about;
}
// 各種ゲッター
public int getImageRes() {
return imageRes;
}
public int getNum() {
return num;
}
public String getTitle() {
return title;
}
public String getWhy01() {
return why01;
}
public String getWhy02() {
return why02;
}
public String getWhy03() {
return why03;
}
public String getAbout() {
return about;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(imageRes);
dest.writeInt(num);
dest.writeString(title);
dest.writeString(why01);
dest.writeString(why02);
dest.writeString(why03);
dest.writeString(about);
}
//
public static final Creator<book> CREATOR = new Creator<book>() {
@Override
public book createFromParcel(Parcel source) {
int imageRes = source.readInt();
int num = source.readInt();
String title = source.readString();
String why01 = source.readString();
String why02 = source.readString();
String why03 = source.readString();
String about = source.readString();
book book = new book (imageRes,num, title, why01,why02,why03, about);
return book;
}
@Override
public book[] newArray(int size) {
return new book[0];
}
};
// リスト1件分のViewをまとめるViewHolder
public static class ViewHolder extends RecyclerView.ViewHolder {
protected View rowView; // 1件分のレイアウトView(クリック処理を実装する用)
protected TextView title; // 自作タイトルの表示用
protected Button deleteBtn; // 1件分のデータを削除するようボタン
protected Button editBtn;
public ViewHolder(@NonNull View itemView) {
super(itemView);
rowView = itemView; // itemView自体を保存(実体は、layout_book_row の LinearLayoutとなる)
title = itemView.findViewById(R.id.title);
deleteBtn = itemView.findViewById(R.id.delete_btn);
editBtn = itemView.findViewById(R.id.edit_btn);
}
public View getRowView() {
return rowView;
}
public TextView getTitle() {
return title;
}
public Button getDeleteBtn() {
return deleteBtn;
}
public Button getEditBtn() {
return editBtn;
}
}
// データとViewHolderを紐づけるAdapterクラス
public static class Adapter extends RecyclerView.Adapter<ViewHolder> {
private List<book> bookList; // 本のリスト
// 本リストを受け取る用のコンストラクタ
public Adapter(List<book> bookList) {
this.bookList = bookList;
}
// ViewHolder生成用メソッド
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// LayoutInflaterを使用し、layout_pan_rowを生成し、ViewHolderの生成も同時に行っている。
return new ViewHolder(
LayoutInflater
.from(parent.getContext())
.inflate(R.layout.layout_book_row, parent, false));
}
// データとViewHolderの紐づけ用メソッド(リストがスクロールされ表示されるデータが切り替わるたびに呼ばれる)
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
final book book = bookList.get(position); // 表示する本のデータを取得
holder.getTitle().setText( book.getTitle()); // 本の名前をViewに設定
// 削除ボタンを押したときの挙動を定義 notifyItemInserted()
holder.getDeleteBtn().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bookList.remove(holder.getAdapterPosition()); // BOOKリストから本の情報を削除
notifyItemRemoved(holder.getAdapterPosition()); // リストの数が変更されたことを通知
}
});
holder.getEditBtn().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), EditDetail.class); // BookDetailActivityに遷移するためのIntent作成
intent.putExtra(MainActivity.EXTRA_PAN, book ); // Intentにクリックし本の情報を設定
v.getContext().startActivity(intent); // アクティビティを起動
}
});
// 1件分のデータがクリックされた時の挙動を定義
holder.getRowView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), BookDetailActivity.class); // PanDetailActivityに遷移するためのIntent作成
intent.putExtra(MainActivity.EXTRA_PAN, book ); // Intentにクリックし本の情報を設定
v.getContext().startActivity(intent); // アクティビティを起動
}
});
}
// リストのデータ数を返却するメソッド
@Override
public int getItemCount() {
return bookList.size();
}
}
}
BookDetaukActivity
package com.example.app19;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class BookDetailActivity extends AppCompatActivity {
private book book; // 送信されてきたパン情報
//編集画面
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_book_detail );
Intent intent = getIntent(); // アクティビティの軌道に使われたIntent取得
book = (book)intent.getParcelableExtra(MainActivity.EXTRA_PAN); // IntentからPan情報を取得
ImageView image = findViewById(R.id.image);
TextView titleText = findViewById(R.id.title);
TextView why01Text = findViewById(R.id.why01);
TextView why02Text = findViewById(R.id.why02);
TextView why03Text = findViewById(R.id.why03);
TextView About = findViewById(R.id.about);
TextView num = findViewById(R.id.num);
// 本情報をViewに設定
image.setImageResource( book.getImageRes());
titleText.setText( book.getTitle());
why01Text.setText( book.getWhy01());
why02Text.setText( book.getWhy02());
why03Text.setText( book.getWhy03());
About.setText( book.getAbout());
num.setText(Integer.toString( book.getNum()));
//num.setText(toString(book.getNum()));
}
}
EditDitailActivity
package com.example.app19;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.EditText;
import android.widget.Button;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class EditDetail extends AppCompatActivity {
private book book; // 送信されてきた本情報
private int number;
//編集画面
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_detail);
Intent intent = getIntent(); // アクティビティの軌道に使われたIntent取得
book = (book)intent.getParcelableExtra(MainActivity.EXTRA_PAN); // IntentからPan情報を取得
ImageView image = findViewById(R.id.image);
final EditText edit_titleText = findViewById(R.id.edit_title);
final EditText edit_why01Text = findViewById(R.id.edit_why01);
EditText edit_why02Text = findViewById(R.id.edit_why02);
EditText edit_why03Text = findViewById(R.id.edit_why03);
EditText edit_About = findViewById(R.id.edit_about);
Button EditBtn = findViewById(R.id.edit_btn);
//本情報をViewに設定
image.setImageResource( book.getImageRes());
edit_titleText.setText( book.getTitle());
edit_why01Text.setText( book.getWhy01());
edit_why02Text.setText( book.getWhy02());
edit_why03Text.setText( book.getWhy03());
edit_About.setText( book.getAbout());
number=book.getNum();
EditBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(edit_titleText.getText().toString().equals("")) { // 未入力ならトーストを表示しonClick()を終了(return)
Toast.makeText(EditDetail.this, "titleを入力してください", Toast.LENGTH_SHORT).show();
return;
}
if(edit_why01Text.getText().toString().equals("")) { // 未入力ならトーストを表示しonClick()を終了(return)
Toast.makeText(EditDetail.this, "01を入力してください", Toast.LENGTH_SHORT).show();
return;
}
Intent intent = new Intent(); // 空のインテント(行先の指定なし)を作成
intent.putExtra(MainActivity.EXTRA_TITLE, edit_titleText.getText().toString()); // MainActivityで定義したEXTRA_NAMEで、入力された名前を設定
intent.putExtra(MainActivity.EXTRA_WHY01, edit_why01Text.getText().toString()); // MainActivityで定義したEXTRA_NAMEで、入力された年齢を設定
//intent.putExtra(MainActivity.EXTRA_WHY01, Integer.parseInt(ageEdit.getText().toString())); // MainActivityで定義したEXTRA_NAMEで、入力された年齢を設定
setResult(RESULT_OK, intent); // アクティビティの結果をRESULT_OK(成功)と返却値をintentとして登録
finish(); // アクティビティを終了(結果をMainActivityに返却)
}
});
}
}
NewAdd.java
package com.example.app19;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.EditText;
import android.view.View;
import android.widget.Button;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
public class NewAdd extends AppCompatActivity {
//新規登録画面
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_add);
ImageView image = findViewById(R.id.add_image);
EditText AddTitleText = findViewById(R.id.add_title);
EditText AddWhy01Text = findViewById(R.id.add_why01);
EditText AddWhy02Text = findViewById(R.id.add_why02);
EditText AddWhy03Text = findViewById(R.id.add_why03);
EditText AddAbout = findViewById(R.id.add_about);
Button AddBtn = findViewById(R.id.add_btn);
findViewById(R.id.add_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(NewAdd.this, MainActivity.class); // RegisterActivityを作っていない場合エラー
startActivity(intent);
}
});
}
}
layout
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/new_btn" />
<Button
android:id="@+id/new_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="登録"
android:textSize="24sp" />
</RelativeLayout>
edit_ditail.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/image"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/pan_bour_bu_ru" />
<EditText
android:id="@+id/edit_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="自分でタイトルを決めるなら"
android:textSize="24sp" />
<EditText
android:id="@+id/edit_why01"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="なぜ、この本を読もうと思ったのか"
android:textSize="24sp" />
<EditText
android:id="@+id/edit_why02"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="この本から何を得たいのか"
android:textSize="24sp" />
<EditText
android:id="@+id/edit_why03"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="この本を読んでどうなりたいか"
android:textSize="24sp" />
<Button
android:id="@+id/edit_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="保存"
android:textSize="24sp" />
<EditText
android:id="@+id/edit_about"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="top|left"
android:text="メモ"
android:textSize="24sp" />
</LinearLayout>
</ScrollView>
layout_book_datail.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/image"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/pan_bour_bu_ru" />
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="title"
android:textSize="24sp" />
<TextView
android:id="@+id/why01"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="why01"
android:textSize="24sp" />
<TextView
android:id="@+id/why02"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="why02"
android:textSize="24sp" />
<TextView
android:id="@+id/why03"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="why03"
android:textSize="24sp" />
<TextView
android:id="@+id/about"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="about"
android:textSize="24sp" />
<TextView
android:id="@+id/num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="about"
android:textSize="24sp" />
</LinearLayout>
</ScrollView>
layout_book_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@drawable/border_bottom"
android:padding="5dp"
android:layout_margin="5dp"
android:focusable="true"
android:clickable="true" >
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="8" />
<Button
android:id="@+id/delete_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="削除" />
<Button
android:id="@+id/edit_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="編集" />
</LinearLayout>
new_add.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/add_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/pan_bour_bu_ru" />
<EditText
android:id="@+id/add_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="自分でタイトルを決めるなら"
android:textSize="24sp" />
<EditText
android:id="@+id/add_why01"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="なぜ、この本を読もうと思ったのか"
android:textSize="24sp" />
<EditText
android:id="@+id/add_why02"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="この本から何を得たいのか"
android:textSize="24sp" />
<EditText
android:id="@+id/add_why03"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="この本を読んでどうなりたいか"
android:textSize="24sp" />
<Button
android:id="@+id/add_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/add_why03"
android:layout_gravity="right"
android:text="保存"
android:textSize="24sp" />
<EditText
android:id="@+id/add_about"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="top|left"
android:hint="メモ"
android:textSize="24sp" />
</LinearLayout>
</ScrollView>
manufest
AndoroidoManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app19">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".BookDetailActivity" /> //追加
<activity android:name=".EditDetail" /> //追加
<activity android:name=".NewAdd" /> //追加
</application>
</manifest>
build.gradle(モジュール:app)
//省略
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.3.1' //追加
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}