將加入記事資料修改的功能,單擊項目將帶入編輯的畫面
新增一NoteActivity,用來編輯記事資料
activity佈局
> activity_note.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_note"
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.NoteActivity"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:inputType="textMultiLine|textPersonName"
android:text=""
android:id="@+id/etTitle"
android:layout_height="70dp"
android:gravity="top|left"
android:background="@drawable/rectangle"
android:padding="5dp"
android:hint="Title" />
<EditText
android:layout_width="match_parent"
android:inputType="textMultiLine|textPersonName"
android:text=""
android:id="@+id/etContent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:scrollHorizontally="false"
android:gravity="top|left"
android:background="@drawable/rectangle"
android:layout_marginTop="5dp"
android:padding="5dp"
android:hint="Content" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:text="取消"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_cancel"
android:layout_weight="1" />
<Button
android:text="確定"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_ok"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
> NoteActivity.java
package com.pingtung.ccstudio.notepadcloud;
import android.app.Activity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class NoteActivity extends AppCompatActivity {
//UI variables
private Button btn_ok, btn_cancel;
private EditText etTitle, etContent;
//intent from caller
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_note);
//find UId
btn_ok = (Button)findViewById(R.id.btn_ok);
btn_cancel = (Button)findViewById(R.id.btn_cancel);
etTitle = (EditText)findViewById(R.id.etTitle);
etContent = (EditText)findViewById(R.id.etContent);
//intent from caller
intent = getIntent();
//若是EDIT_NOTE action,則顯示原本的title及content內容
if(intent.getAction().equals("com.pingtung.ccstudio.notepadcloud.EDIT_NOTE")){
String title,content;
title = intent.getStringExtra("TITLE");
content = intent.getStringExtra("CONTENT");
etTitle.setText(title);
etContent.setText(content);
}
View.OnClickListener onClickListener = new View.OnClickListener(){
@Override
public void onClick(View view) {
if(view.getId()==R.id.btn_ok){
String title,content;
title = etTitle.getText().toString();
content = etContent.getText().toString();
if(title.equals("") || content.equals("")){
Toast.makeText(NoteActivity.this,"請輸入title及content",Toast.LENGTH_SHORT).show();
return;
}
intent.putExtra("TITLE",title);
intent.putExtra("CONTENT",content);
setResult(Activity.RESULT_OK, intent);
}
finish();
}
};
btn_ok.setOnClickListener(onClickListener);
btn_cancel.setOnClickListener(onClickListener);
}
}
背景以圓角長方形填滿
> rectangle.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#C5CAE9"/>
<corners
android:radius="15dp" />
</shape>
在manifest中加入開啟NoteActivity的actions(add及edit)
> AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pingtung.ccstudio.notepadcloud">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
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=".LoginActivity" />
<activity android:name=".NoteActivity">
<intent-filter>
<!-- 新增用的名稱 -->
<action android:name="com.pingtung.ccstudio.notepadcloud.ADD_NOTE" />
<!-- 修改用的名稱 -->
<action android:name="com.pingtung.ccstudio.notepadcloud.EDIT_NOTE" />
<!-- 一定要加入,內容固定不變 -->
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
主畫面佈局刪除EditText,也使用NoteActivity記事新增
> 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/textView6" />
</RelativeLayout>
主畫面控制加入修改記事程式碼,並將新增的功能改為啟動NoteActivity
> 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.HashMap;
import java.util.List;
import java.util.Map;
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;
//start activity requestCode
private final static int REQUEST_ADD = 0;
private final static int REQUEST_EDIT = 1;
@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);
}
//子目錄下若有資料異動(value)會被呼叫
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
Item item = dataSnapshot.getValue(Item.class);
String key = dataSnapshot.getKey();
Log.d("android","onChildChanged: "+ key);
ItemPlus tmp;
for(int i=0;i<itemPlusList.size();i++){
tmp = itemPlusList.get(i);
if(tmp.getKey().equals(key)){
itemPlusList.set(i,new ItemPlus(item,key));
break;
}
}
}
@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;
}
});
//註冊listView單擊事件
//修改note內容
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
final ItemPlus itemPlus = itemPlusList.get(position);
Intent intent = new Intent();
intent.setAction("com.pingtung.ccstudio.notepadcloud.EDIT_NOTE");
intent.putExtra("TITLE",itemPlus.getTitle());
intent.putExtra("CONTENT",itemPlus.getContent());
intent.putExtra("KEY",itemPlus.getKey());
startActivityForResult(intent,REQUEST_EDIT);
}
});
}
@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:
Intent intent = new Intent();
intent.setAction("com.pingtung.ccstudio.notepadcloud.ADD_NOTE");
startActivityForResult(intent,REQUEST_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);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(RESULT_OK==resultCode){
String title, content;
title = data.getStringExtra("TITLE");
content = data.getStringExtra("CONTENT");
if(REQUEST_ADD==requestCode){
mRef.push().setValue(new Item(title,content));
}else if(REQUEST_EDIT==requestCode){
String key;
Map<String,Object> map = new HashMap<>();
key = data.getStringExtra("KEY");
//這邊和setValue比較不同,需將item轉成map的格式
//才能使用updateChildren
map.put(key, new Item(title,content).toMap());
mRef.updateChildren(map);
}
}
}
}
這邊有一點要特別注意,修改記事時使用到的updateChildren(Map<String, Object> update)這邊Object必需是一個Map物件()
故在Item class中加入一轉換map物件的函式
> Item.java
package com.pingtung.ccstudio.notepadcloud;
import java.util.HashMap;
import java.util.Map;
/**
* 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;
}
public Map<String, Object> toMap() {
HashMap<String, Object> result = new HashMap<>();
result.put("title", title);
result.put("content", content);
return result;
}
}
這樣子就完成整個記事本的基本功能了
> 完整程式碼(Github)


沒有留言:
張貼留言