加入記事本新增/刪除記事資料的功能
久按記事項目,即會跳出詢問刪除視窗
另外在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: 雲端記事本<三>:修改記事資料


沒有留言:
張貼留言