加入記事本新增/刪除記事資料的功能
久按記事項目,即會跳出詢問刪除視窗
另外在firebase console裡修改Database的規則如下:
{ "rules": { "users":{ "$uid":{ ".read": "$uid === auth.uid", ".write": "$uid === auth.uid" } } } }讓每個登入的使用者用自身的uid建立資料夾
並且只能存取自己這個資料夾下的資料
首先新增Item class,用來儲存每一筆記事資料的內容
這邊只有兩筆String資料,分別是title & content
> Item.java
package com.pingtung.ccstudio.notepadcloud; /** * Created by crowd_000 on 10/6/2016. */ public class Item { private String title; private String content; public Item(){ } public Item(String title, String content) { this.title = title; this.content = content; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }這邊要為每一筆instance variable,撰寫getter/setter methods 及加入無參數建構子,才能讓firebase database作read/write (若沒宣告會直接compilation failed)
新增ItemPlus class,相較於Item class,多儲存一筆key值,用來刪除資料用
> ItemPlus.java
package com.pingtung.ccstudio.notepadcloud; /** * Created by crowd_000 on 10/6/2016. */ public class ItemPlus extends Item { private String key; public ItemPlus() { } public ItemPlus(Item item, String key) { super(item.getTitle(),item.getContent()); this.key = key; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } }
新增ItemPlusAdapter class,將資料顯示在listView
> ItemPlusAdapter.java
package com.pingtung.ccstudio.notepadcloud; import android.content.Context; import android.support.annotation.NonNull; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; import java.util.List; /** * Created by crowd_000 on 10/6/2016. */ public class ItemPlusAdapter extends ArrayAdapter<ItemPlus> { private Context context; private int resource; private List<ItemPlus> list; private LayoutInflater layoutInflater; public ItemPlusAdapter(Context context, int resource, List<ItemPlus> list) { super(context, resource, list); this.context = context; this.resource = resource; this.list = list; layoutInflater = LayoutInflater.from(context); } @NonNull @Override public View getView(int position, View convertView, ViewGroup parent) { View itemView; ViewHolder viewHolder; ItemPlus itemPlus = list.get(position); if(convertView==null){ itemView = layoutInflater.inflate(resource,null); viewHolder = new ViewHolder((TextView) itemView.findViewById(R.id.tvTitle), (TextView) itemView.findViewById(R.id.tvContent)); itemView.setTag(viewHolder); }else{ itemView = convertView; viewHolder = (ViewHolder) itemView.getTag(); } viewHolder.tvTitle.setText(itemPlus.getTitle()); viewHolder.tvContent.setText(itemPlus.getContent()); return itemView; } private class ViewHolder{ TextView tvTitle,tvContent; public ViewHolder(TextView tvTitle,TextView tvContent){ this.tvTitle = tvTitle; this.tvContent = tvContent; } } }
ListView單行佈局
> single_line.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center"> <TextView android:text="TextView" android:layout_height="wrap_content" android:id="@+id/tvTitle" android:textSize="24sp" android:layout_width="85dp" android:maxLines="1" android:gravity="center" /> <TextView android:text="TextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tvContent" android:layout_weight="1" android:textSize="14sp" android:maxLines="2" /> </LinearLayout>
主畫面佈局新增ListView及EditText
> activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.pingtung.ccstudio.notepadcloud.MainActivity"> <TextView android:text="LoginUser:" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:id="@+id/textView6" android:textSize="18sp" android:textColor="@android:color/black" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="UserName" android:id="@+id/tvUser" android:textSize="18sp" android:layout_marginLeft="17dp" android:layout_marginStart="17dp" android:layout_alignParentBottom="true" android:layout_toRightOf="@+id/textView6" android:layout_toEndOf="@+id/textView6" android:textColor="@android:color/holo_red_light" /> <ListView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:id="@+id/listView" android:dividerHeight="2dp" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:layout_above="@+id/linearLayout"/> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@+id/textView6" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:id="@+id/linearLayout"> <EditText android:layout_height="wrap_content" android:inputType="textPersonName" android:text="" android:ems="10" android:id="@+id/etTitle" android:layout_width="80dp" android:hint="title" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPersonName" android:text="" android:ems="10" android:id="@+id/etContent" android:layout_weight="1" android:hint="content" /> </LinearLayout> </RelativeLayout>
主畫面控制加入新增/刪除記事功能
> MainActivity.java
package com.pingtung.ccstudio.notepadcloud; import android.content.DialogInterface; import android.content.Intent; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseUser; import com.google.firebase.database.ChildEventListener; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { //UI variables private TextView tvUser; private ListView listView; private EditText etTitle, etContent; //餵給listView的相關變數 private ItemPlusAdapter itemPlusAdapter; private List<ItemPlus> itemPlusList; //Firebase instance variables private FirebaseAuth auth; private FirebaseUser user; private FirebaseDatabase firebaseDatabase; private DatabaseReference mRef; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //local variable String userUid=""; //find UId tvUser = (TextView)findViewById(R.id.tvUser); listView = (ListView)findViewById(R.id.listView); etTitle = (EditText)findViewById(R.id.etTitle); etContent = (EditText)findViewById(R.id.etContent); //取得auth實體(只有一個實體app內皆能共用) auth = FirebaseAuth.getInstance(); user = auth.getCurrentUser(); //若無登入帳戶,則getCurrentUser()傳回null //開啟LoginActivity if(user==null){ startActivity(new Intent(this,LoginActivity.class)); finish(); }else{ tvUser.setText(user.getEmail()); userUid = user.getUid(); } //實體化餵給listView的相關變數: arrayList, adapter itemPlusList = new ArrayList<>(); itemPlusAdapter = new ItemPlusAdapter(MainActivity.this,R.layout.single_line,itemPlusList); listView.setAdapter(itemPlusAdapter); //取得firebase根目錄下"/users/$uid"的reference //不同登入的使用者有不同的Uid,無法存取其他人的資料 firebaseDatabase = FirebaseDatabase.getInstance(); mRef = firebaseDatabase.getReference("users/"+userUid); //對使用者根目錄(/users/$uid)註冊一子目錄變更監聽器 ChildEventListener childEventListener = new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { String key = dataSnapshot.getKey(); Log.d("android","onChildAdded: "+ key); Item item = dataSnapshot.getValue(Item.class); ItemPlus itemPlus = new ItemPlus(item, key); itemPlusList.add(itemPlus); } @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) { } @Override public void onChildRemoved(DataSnapshot dataSnapshot) { String key = dataSnapshot.getKey(); Log.d("android", "onChildRemoved: " + key); ItemPlus tmp=null; for(ItemPlus ip:itemPlusList){ if(ip.getKey().equals(key)){ tmp = ip; break; } } if(itemPlusList.contains(tmp)) itemPlusList.remove(tmp); } @Override public void onChildMoved(DataSnapshot dataSnapshot, String s) { } @Override public void onCancelled(DatabaseError databaseError) { } }; mRef.addChildEventListener(childEventListener); //註冊使用者根目錄監聽器 //只要子目錄值一有變更,便會收到通知 //通知adapter資料有變更,刷新listView顯示 ValueEventListener valueEventListener = new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Log.d("android","onDataChange"); itemPlusAdapter.notifyDataSetChanged(); } @Override public void onCancelled(DatabaseError databaseError) { } }; mRef.addValueEventListener(valueEventListener); //註冊listView長按事件 //詢問是否刪除 listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long l) { final ItemPlus itemPlus = itemPlusList.get(position); AlertDialog.Builder ab = new AlertDialog.Builder(MainActivity.this); ab.setTitle(itemPlus.getTitle()) .setMessage("是否刪除此筆紀錄?") .setIcon(R.mipmap.ic_launcher) .setCancelable(true); ab.setPositiveButton("確定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mRef.child(itemPlus.getKey()).removeValue(); } }); ab.setNegativeButton("取消", null); ab.show(); return true; } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main,menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()){ case R.id.add: String title = etTitle.getText().toString(); String content = etContent.getText().toString(); if(title.equals("") || content.equals("")){ Toast.makeText(MainActivity.this,"請輸入title及content",Toast.LENGTH_SHORT).show(); }else{ //使用push()讓系統自動產生key值 //key值依timestamp產生,不會重複且不斷向上遞增 mRef.push().setValue(new Item(title,content)); etTitle.setText(""); etContent.setText(""); } break; case R.id.logout: //將auth登出 auth.signOut(); startActivity(new Intent(this,LoginActivity.class)); finish(); break; } return super.onOptionsItemSelected(item); } }
在menu resource中新增add功能就完成囉
> menu_main.xml
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:apps="http://schemas.android.com/apk/res-auto"> <item android:title="add" android:id="@+id/add" android:icon="@android:drawable/ic_input_add" apps:showAsAction="always"></item> <item android:title="logout" android:id="@+id/logout" apps:showAsAction="never"></item> </menu>
> 完整程式碼(Github)
next: 雲端記事本<三>:修改記事資料
沒有留言:
張貼留言