记事本2
在这个练习我们 将增加一个Activity到我们的应用程序。而且用户不但可以创建记事本,编辑记事本还可以删除已存在的记事本。
通过这个练习我们将可以学习到下面几个知识点:
l 创建一个新的Activity 并添加到manifest
l 使用startActivityForResult()异步调用其它Activity
l 在Activity之间传递数据包
l 怎么作用更多高级屏幕布局
l 怎么创建一个菜单上下文
1)先改个错
官方提供的notepad2有一个方法写错了。
打开src/com/android/demo/notepad2/Notepadv2.java定位到97行。
把方法onCreateOptionsMenu改成onCreateContextMenu。
2)新增的字符串和方法
打开字符串资源(res/values/strings.xml),增加了几个字符串。
<string name="menu_delete">Delete Note</string>
<string name="title">Title</string>
<string name="body">Body</string>
<string name="confirm">Confirm</string>
<string name="edit_note">Edit Note</string>
Notepadv2添加了一个成员mNotesCursor
private Cursor mNotesCursor;
fillData()方法做相应修改,粉红色部分。
private void fillData()
{
// Get all of the rows from the database and create the item list
mNotesCursor = mDbHelper.fetchAllNotes();
startManagingCursor(mNotesCursor);
// Create an array to specify the fields we want to display in the list
// (only TITLE)
String[] from = new String[]
{ NotesDbAdapter.KEY_TITLE };
// and an array of the fields we want to bind those fields to (in this
// case just text1)
int[] to = new int[]
{ R.id.text1 };
// Now create a simple cursor adapter and set it to display
SimpleCursorAdapter notes = new SimpleCursorAdapter(this,
R.layout.notes_row, mNotesCursor, from, to);
setListAdapter(notes);
}
添加了几个新的方法
onCreateContextMenu()
onContextItemSelected()
onListItemClick()
onActivityResult()
3)创建一个可以删除记事本的菜单
在方法onCreate最后添加菜单注册(粉红色)
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.notes_list);
mDbHelper = new NotesDbAdapter(this);
mDbHelper.open();
fillData();
registerForContextMenu(getListView());
}
public void registerForContextMenu (View view)为view注册一个上下文菜单,当菜单显示时,将会调用方法 onCreateContextMenu(ContextMenu, View, ContextMenuInfo)
getListView()取ListView对象。
为onCreateContextMenu增加代码
@Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo)
{
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, DELETE_ID, 0, R.string.menu_delete);
}
4)为onContextItemSelected增加代码
我已经为我们的ListView 注册了上下文件菜单并且定义了上下文菜单项,菜单项被选中时,将会调用onContextItemSelected
@Override
public boolean onContextItemSelected(MenuItem item)
{
switch(item.getItemId())
{
case DELETE_ID:
AdapterContextMenuInfo info = ()item.getMenuInfo();
mDbHelper.deleteNote(info.id);
return true;
}
return super.onContextItemSelected(item);
}
AdapterContextMenuInfo为onCreateContextMenu提供额外的菜单信息。
这里的id就是菜单项的位置。
5)创建记事本createNote
这里跟第一个练习不同。
这里我们用了“意图”。意图是一个操作的描述。
startActivityForResult将Activity ,并且当启动完后,将回调onActivityResult。
startActivity也可以启动一个Activity,但它不回调通知我们。
关于“意图”的更多内容请参考
http://androidappdocs.appspot.com/guide/topics/intents/intents-filters.html
注意:这里的NoteEdit现在还没有创建,等一下将会创建。
6)onListItemClick
@Override
protected void onListItemClick(ListView l, View v, int position, long id)
{
super.onListItemClick(l, v, position, id);
Intent i = new Intent(this, NoteEdit.class);
i.putExtra(NotesDbAdapter.KEY_ROWID, id);
i.(NotesDbAdapter.KEY_TITLE, c.getString(
c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
c.(NotesDbAdapter.KEY_BODY)));
}
当用户单击列表某一项时。将会调用
void onListItemClick(ListView l, View v, int position, long id);
它一共有四个参数:
ListView就是用户单击项所在的列表
View 就是我们单击项的视图
Position 单击在列表的位置
Id 单击项的id
通过moveToPosition把光标移到相应位置。
putExtra增加额外的数据到意图里。
getColumnIndexOrThrow返回给定列名称的从零开始的索引
注意:这里之所以把光标mNotesCursor赋给一个本地的光标,是为了优化。存取本地变量效率比较高。
7) 回调函数onActivityResult
@Override
protected void onActivityResult(int requestCode, int resultCode,Intent intent)
{
super.onActivityResult(requestCode, resultCode, intent);
switch (requestCode)
{
String title = extras.getString(NotesDbAdapter.KEY_TITLE);
String body = extras.getString(NotesDbAdapter.KEY_BODY);
mDbHelper.createNote(title, body);
fillData();
break;
Long mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
if (mRowId != null)
{
String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE);
String editBody = extras.getString(NotesDbAdapter.KEY_BODY);
mDbHelper.updateNote(mRowId, editTitle, editBody);
}
fillData();
break;
}
}
Bundle 相当于一个容器。
getExtras从意图里取额外的数据。(那些数据是通过putExtra加到意图里的)
我们之前的startActivityForResult调用给第二个参数传了ACTIVITY_CREATE和ACTIVITY_EDIT在这里用一个switch来区别是哪个回调过来。
看ACTIVITY_CREATE里的代码。这里是创建一个记事本,看看他们跟第一个练习(http://www.cnblogs.com/fangyukuan/archive/2010/04/05/1704806.html),方法 createNote的差别。
8)note_edit.xml
这个是我们的编辑记事本的界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title" />
<EditText android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/body" />
<EditText android:id="@+id/body"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:scrollbars="vertical" />
<Button android:id="@+id/confirm"
android:text="@string/confirm"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
9)创建NoteEdit 类
在com.android.demo.notepad2右键。New > Class
在弹出的对话框:
在name输入:NoteEdit
在Superclass输入:android.app.Activity
然后点击完成按钮。
在打开的NoteEdit类中,右键,选择Source > Override/Implement Methods...
找到onCreate(Bundle)在前面打勾。并点击OK。
这样就可以对方法onCreate进行重写。
@Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
10) 完善NoteEdit 类的onCreate
声明三个成员
private EditText mTitleText;
private EditText mBodyText;
private Long mRowId;
在onCreate里加以下代码
setContentView(R.layout.note_edit);
// 通过id找到相应组件
mTitleText = (EditText)findViewById(R.id.title);
mBodyText = (EditText)findViewById(R.id.body);
Button confirmButton = (Button)findViewById(R.id.confirm);
// 从意图取数据,并应用到想关组件,如设置标题等。
mRowId = null;
Bundle extras = getIntent().getExtras();
if (null != extras)
{
String title = extras.getString(NotesDbAdapter.KEY_TITLE);
String body = extras.getString(NotesDbAdapter.KEY_BODY);
mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
if (null != title)
{
mTitleText.setText(title);
}
if (null != body)
{
mBodyText.setText(body);
}
}
// 侦听按钮单击事件
confirmButton.setOnClickListener(new View.OnClickListener()
{
@Override
{
// TODO Auto-generated method stub
}
});
11)完善onClick
@Override
public void onClick(View v)
{
// 创建一个Bundle并把要返回的数据放到里面去。
Bundle bundle = new Bundle();
bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
if (null != mRowId)
{
bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
}
// 创建一个意图,差把Bundle加进去,返回差结束这个Activity
Intent mIntent = new Intent();
mIntent.putExtras(bundle);
setResult(RESULT_OK, mIntent);
finish();
}
12) 修改AndroidManifest
l 双击文件AndroidManifest.xml
l 单击下面的标签Application
l 在 Application Nodes模块单击Add按钮。
l 在弹出的对话框中选择Activity
在 Application Nodes模块单击Activity,在右边的Name输入:.NoteEdit
选择AndroidManifest.xml标签看源代码可以看到。我们新增的代码。
<activity android:name=".NoteEdit"></activity>
这样系统就知道我们新建了一个activity而且可以被调用。
13)运行
点击Add Note增加一个记事本。这个时候将出现下面的界面。
14) 仍然存在错误
当我们在编辑记事本时,如果没有点击提交按钮,而是按了返回按钮的时候。将出现错误的提示。
返回到记事本时,我们可以发现,刚才编辑的内容不见了。记事本3将解决这个问题。
http://www.cnblogs.com/fangyukuan/archive/2010/04/07/1704841.html
2010-4-7
fangyukuan