將加入記事資料修改的功能,單擊項目將帶入編輯的畫面
新增一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)
沒有留言:
張貼留言