今まで学んできた様々な技術を織り交ぜてtodoアプリを作ってみよう。
Q1
todoアプリを作成せよ。データをファイルに保存し、再起動した際に情報を復元できるようにすること。
必要であれば以下のアイコンをダウンロードして使用してよい。
[素材]



[実行例]
スタート画面
todoを登録するボタンがある。

ボタンを押すとSubに遷移して入力フォームが現れる

todoを入力し、アイコンを選ぶ

登録ボタンを押すと、Mainに遷移しリストビューに登録されている。

何件か登録してみる。

項目をタップするとSubに遷移し、編集ができる。この時ボタンの文言は「更新」となっていることに注意

todoとアイコンを編集し、更新ボタンを押す。

Mainに戻り、情報が更新されている。

項目を長押しすると、確認のダイアログが表示される。

はいを押すと項目が削除される(いいえでキャンセル)

●activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:onClick="btAdd"
android:text="todo追加"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp" />
<ListView
android:id="@+id/lv"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp" />
</android.support.constraint.ConstraintLayout>
●activity_sub.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:text="todo"
app:layout_constraintLeft_toLeftOf="parent"
android:id="@+id/textView2"
app:layout_constraintBaseline_toBaselineOf="@+id/etTodo" />
<EditText
android:id="@+id/etTodo"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text=""
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintLeft_toRightOf="@+id/textView2"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
app:layout_constraintRight_toRightOf="parent" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="8dp"
android:text="icon"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etTodo" />
<RadioGroup
android:id="@+id/rg"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:orientation="horizontal"
app:layout_constraintLeft_toRightOf="@+id/textView3"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etTodo">
<RadioButton
android:id="@+id/rb1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="赤" />
<RadioButton
android:id="@+id/rb2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="緑" />
<RadioButton
android:id="@+id/rb3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="青" />
</RadioGroup>
<Button
android:id="@+id/btBack"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:onClick="btBack"
android:text="登録"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/rg" />
</android.support.constraint.ConstraintLayout>
●list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<ImageView
android:id="@+id/iv"
android:layout_width="60dp"
android:layout_height="60dp"
app:srcCompat="@drawable/star_b"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="0dp"
android:layout_marginLeft="0dp"
app:layout_constraintLeft_toLeftOf="parent" />
<TextView
android:id="@+id/tvTodo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:padding="10dp"
android:text="TextView"
app:layout_constraintLeft_toRightOf="@+id/iv"
tools:layout_editor_absoluteY="25dp" />
</android.support.constraint.ConstraintLayout>
●Todo.java
import java.io.Serializable;
public class Todo implements Serializable {
private String todo;
private int resId;
public Todo(String todo,int resId){
this.todo=todo;
this.resId=resId;
}
public String getTodo(){
return this.todo;
}
public int getResId() {
return this.resId;
}
public void setTodo(String todo) {
this.todo=todo;
}
public void setResId(int resId){
this.resId=resId;
}
}
●TodoAdapter.java
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
public class TodoAdapter extends BaseAdapter {
private LayoutInflater inflater;
private int layout;
private List<Todo> list;
public TodoAdapter(Context c,int layout,List<Todo> list){
inflater=((Activity)c).getLayoutInflater();
this.layout=layout;
this.list=list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Todo getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Todo todo=this.getItem(position);
ViewHolder holder;
if(convertView == null){
convertView=inflater.inflate(this.layout,null);
holder=new ViewHolder(convertView);
convertView.setTag(holder);
}else{
holder=(ViewHolder)convertView.getTag();
}
holder.iv.setImageResource(todo.getResId());
holder.tvTodo.setText(todo.getTodo());
return convertView;
}
private static class ViewHolder{
TextView tvTodo;
ImageView iv;
public ViewHolder(View v){
tvTodo=(TextView)v.findViewById(R.id.tvTodo);
iv=(ImageView)v.findViewById(R.id.iv);
}
}
}
●MyDialog.java
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
public class MyDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle b=this.getArguments();
final Todo todo=(Todo)b.getSerializable("todo");
AlertDialog.Builder builder=new AlertDialog.Builder(getActivity());
builder.setTitle("確認")
.setMessage(todo.getTodo()+"を削除してよろしいですか?")
.setPositiveButton("はい", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
MainActivity activity=(MainActivity)getActivity();
activity.removeItem(todo);
}
})
.setNegativeButton("いいえ", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
return builder.create();
}
}
●MainActivity.java
import android.app.DialogFragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
public static final int ADD=1,UPDATE=2;
private List<Todo> list=new ArrayList<>();
private TodoAdapter adapter;
private ListView lv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Object ret=this.readFile();
if(ret != null){
list=(List<Todo>)ret;
}
lv=(ListView)findViewById(R.id.lv);
adapter=new TodoAdapter(this,R.layout.list_item,list);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent i=new Intent(MainActivity.this,SubActivity.class);
i.putExtra("requestCode",UPDATE);
i.putExtra("todo",list.get(position));
i.putExtra("index",position);
startActivityForResult(i,UPDATE);
}
});
lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
Bundle b=new Bundle();
b.putSerializable("todo",list.get(position));
DialogFragment dialog=new MyDialog();
dialog.setArguments(b);
dialog.show(getFragmentManager(),"tag");
return true;
}
});
}
public void btAdd(View v){
Intent i=new Intent(this,SubActivity.class);
i.putExtra("requestCode",ADD);
startActivityForResult(i,ADD);
}
public void removeItem(Todo todo){
list.remove(todo);
adapter.notifyDataSetChanged();
Toast.makeText(this,todo.getTodo()+"を削除しました。",Toast.LENGTH_SHORT).show();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
Todo t=(Todo)data.getSerializableExtra("todo");
switch(requestCode){
case ADD:
list.add(t);
break;
case UPDATE:
int index=data.getIntExtra("index",-1);
list.set(index,t);
break;
}
adapter.notifyDataSetChanged();
}
}
@Override
protected void onPause() {
super.onPause();
saveFile();
}
private void saveFile() {
ObjectOutputStream oos=null;
try {
FileOutputStream fos=openFileOutput("data.dat",MODE_PRIVATE);
oos=new ObjectOutputStream(fos);
oos.writeObject(list);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(oos != null){
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private Object readFile(){
Object ret=null;
ObjectInputStream ois=null;
try {
FileInputStream fis=openFileInput("data.dat");
ois=new ObjectInputStream(fis);
ret=ois.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if(ois != null){
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return ret;
}
}
●SubActivity.java
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;
public class SubActivity extends AppCompatActivity {
private EditText etTodo;
private RadioGroup rg;
private Button btBack;
private Todo t;
private int requestCode;
private int index;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sub);
etTodo=(EditText)findViewById(R.id.etTodo);
rg=(RadioGroup)findViewById(R.id.rg);
btBack=(Button)findViewById(R.id.btBack);
Intent i=this.getIntent();
requestCode=i.getIntExtra("requestCode",-1);
index=i.getIntExtra("index",-1);
if(requestCode == MainActivity.UPDATE){
btBack.setText("更新");
t=(Todo)i.getSerializableExtra("todo");
etTodo.setText(t.getTodo());
switch(t.getResId()){
case R.drawable.star_r:
rg.check(R.id.rb1);
break;
case R.drawable.star_g:
rg.check(R.id.rb2);
break;
case R.drawable.star_b:
rg.check(R.id.rb3);
break;
}
}
}
public void btBack(View v){
Intent i=new Intent();
String todo=etTodo.getText().toString();
int resId;
int checkedId=rg.getCheckedRadioButtonId();
switch(checkedId){
case R.id.rb1:
resId=R.drawable.star_r;
break;
case R.id.rb2:
resId=R.drawable.star_g;
break;
case R.id.rb3:
resId=R.drawable.star_b;
break;
default:
resId=R.drawable.star_r;
break;
}
switch(this.requestCode){
case MainActivity.ADD:
t=new Todo(todo,resId);
break;
case MainActivity.UPDATE:
t.setTodo(todo);
t.setResId(resId);
i.putExtra("index",index);
break;
}
i.putExtra("todo",t);
this.setResult(RESULT_OK,i);
this.finish();
}
}

コメント