分类:C#、Android、VS2015;

创建日期:2016-02-23

一、简介

这个例子演示如何实现一个简单的记事本功能。

该例子提前使用了后面章节将要介绍的SQLLite数据库。

二、示例—ch1205NotePadDemo

1、运行截图

单击右上角【…】会弹出【添加】菜单项,长按某条记录会弹出快捷菜单【删除】项。

2、主要设计步骤

(1)添加引用

鼠标右击【引用】à【添加引用】,在弹出的窗口中勾选“System.Data”和“System.Data.SQlite”,如下图所示:

注意:不需要通过NuGet添加SQLite程序包,只需要按这种方式添加即可。

(2)添加图片

到Android SDK API 23的Samples的NotePad例子下找到app_notes.png,将其添加到该项目中,并将其换名为ch12_app_notes.png。

(3)添加ch1205_NoteEditor.axml文件

<?xml version="1.0" encoding="utf-8"?>
<view xmlns:android="http://schemas.android.com/apk/res/android"
class="MyDemos.SrcDemos.ch1205LinedEditText"
android:id="@+id/note"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dip"
android:scrollbars="vertical"
android:fadingEdge="vertical"
android:gravity="top"
android:textSize="22sp"
android:capitalize="sentences" />

(4)添加ch1205_Main.axml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#ffffff"
android:padding="10px">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ch12_app_notes" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="6px">
<TextView
android:id="@+id/body"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/modified"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>

(5)添加ch1205Note.cs文件

using System;
namespace MyDemos.SrcDemos
{
class ch1205Note : Java.Lang.Object
{
public long Id { get; set; }
public string Body { get; set; }
public DateTime ModifiedTime { get; set; } public ch1205Note()
{
Id = -1L;
Body = string.Empty;
} public ch1205Note(long id, string body, DateTime modified)
{
Id = id;
Body = body;
ModifiedTime = modified;
} public override string ToString()
{
return ModifiedTime.ToString();
}
}
}

(6)添加ch1205LinedEditText.cs文件

using Android.Content;
using Android.Runtime;
using Android.Widget;
using Android.Graphics;
using Android.Util; namespace MyDemos.SrcDemos
{
[Register("MyDemos.SrcDemos.ch1205LinedEditText")]
class ch1205LinedEditText : EditText
{
private Rect rect;
private Paint paint; // 为了LayoutInflater需要提供此构造函数
public ch1205LinedEditText(Context context, IAttributeSet attrs)
: base(context, attrs)
{
rect = new Rect();
paint = new Paint();
paint.SetStyle(Android.Graphics.Paint.Style.Stroke);
paint.Color = Color.LightGray;
} protected override void OnDraw(Canvas canvas)
{
int count = LineCount;
for (int i = 0; i < count; i++)
{
int baseline = GetLineBounds(i, rect);
canvas.DrawLine(rect.Left, baseline + 1, rect.Right, baseline + 1, paint);
}
base.OnDraw(canvas);
}
}
}

(7)添加ch1205NoteRepository.cs文件

using System;
using System.Collections.Generic;
using Mono.Data.Sqlite; namespace MyDemos.SrcDemos
{
class ch1205NoteRepository
{
private static string db_file = "notes.db3"; private static SqliteConnection GetConnection()
{
var dbPath = System.IO.Path.Combine(
System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal), db_file);
bool exists = System.IO.File.Exists(dbPath);
if (!exists) SqliteConnection.CreateFile(dbPath);
var conn = new SqliteConnection("Data Source=" + dbPath);
if (!exists) CreateDatabase(conn);
return conn;
} private static void CreateDatabase(SqliteConnection connection)
{
var sql = "CREATE TABLE ITEMS (Id INTEGER PRIMARY KEY AUTOINCREMENT, Body ntext, Modified datetime);";
connection.Open();
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
} // Create a sample note to get the user started
sql = "INSERT INTO ITEMS (Body, Modified) VALUES (@Body, @Modified);";
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("@Body", "今天有个约会");
cmd.Parameters.AddWithValue("@Modified", DateTime.Now);
cmd.ExecuteNonQuery();
}
connection.Close();
} public static IEnumerable<ch1205Note> GetAllNotes()
{
var sql = "SELECT * FROM ITEMS;";
using (var conn = GetConnection())
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = sql;
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
yield return new ch1205Note(
reader.GetInt32(0),
reader.GetString(1),
reader.GetDateTime(2));
}
}
}
}
} public static ch1205Note GetNote(long id)
{
var sql = "SELECT * FROM ITEMS WHERE Id = id;";
using (var conn = GetConnection())
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = sql;
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
return new ch1205Note(reader.GetInt32(0), reader.GetString(1), reader.GetDateTime(2));
else
return null;
}
}
}
} public static void DeleteNote(ch1205Note note)
{
var sql = string.Format("DELETE FROM ITEMS WHERE Id = {0};", note.Id);
using (var conn = GetConnection())
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
}
}
} public static void SaveNote(ch1205Note note)
{
using (var conn = GetConnection())
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
if (note.Id < 0)
{
// Do an insert
cmd.CommandText = "INSERT INTO ITEMS (Body, Modified) VALUES (@Body, @Modified); SELECT last_insert_rowid();";
cmd.Parameters.AddWithValue("@Body", note.Body);
cmd.Parameters.AddWithValue("@Modified", DateTime.Now);
note.Id = (long)cmd.ExecuteScalar();
}
else
{
// Do an update
cmd.CommandText = "UPDATE ITEMS SET Body = @Body, Modified = @Modified WHERE Id = @Id";
cmd.Parameters.AddWithValue("@Id", note.Id);
cmd.Parameters.AddWithValue("@Body", note.Body);
cmd.Parameters.AddWithValue("@Modified", DateTime.Now);
cmd.ExecuteNonQuery();
}
}
}
}
}
}

(8)添加ch1205NoteAdapter.cs文件

using Android.App;
using Android.Content;
using Android.Widget; namespace MyDemos.SrcDemos
{
class ch1205NoteAdapter : ArrayAdapter
{
private Activity activity; public ch1205NoteAdapter(Activity activity, Context context, int textViewResourceId, ch1205Note[] objects)
: base(context, textViewResourceId, objects)
{
this.activity = activity;
} public override Android.Views.View GetView(int position, Android.Views.View convertView, Android.Views.ViewGroup parent)
{
//Get our object for this position
var item = (ch1205Note)GetItem(position); // 如果convertView不为null则重用它,否则从当前布局中填充(inflate)它。
// 由于这种方式不是每次都填充一个新的view,因此可提高性能。
var view = (convertView ?? activity.LayoutInflater.Inflate(
Resource.Layout.ch1205_Main, parent, false)) as LinearLayout; view.FindViewById<TextView>(Resource.Id.body).Text = Left(item.Body.Replace("\n", " "), 25);
view.FindViewById<TextView>(Resource.Id.modified).Text = item.ModifiedTime.ToString(); return view;
} private string Left(string text, int length)
{
if (text.Length <= length) return text; return text.Substring(0, length);
}
}
}

(9)添加ch1205NoteEditorActivity.cs文件

using Android.App;
using Android.Content;
using Android.OS;
using Android.Widget;
using Android.Content.PM; namespace MyDemos.SrcDemos
{
[Activity(Label = "ch1205NoteEditorActivity",
ScreenOrientation = ScreenOrientation.Sensor,
ConfigurationChanges = ConfigChanges.KeyboardHidden | ConfigChanges.Orientation)]
public class ch1205NoteEditorActivity : Activity
{
private ch1205Note note;
private EditText text_view; protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.ch1205_NoteEditor); text_view = FindViewById<EditText>(Resource.Id.note);
var note_id = Intent.GetLongExtra("note_id", -1L);
if (note_id < 0) note = new ch1205Note();
else note = ch1205NoteRepository.GetNote(note_id);
} protected override void OnResume()
{
base.OnResume();
text_view.SetTextKeepState(note.Body);
} protected override void OnPause()
{
base.OnPause();
// 如果是新建的记事本且没有内容,不保存直接返回。
if (IsFinishing && note.Id == -1 && text_view.Text.Length == 0)
return;
// 保存记事本
note.Body = text_view.Text;
ch1205NoteRepository.SaveNote(note);
}
}
}

(10)添加ch1205NotePadMain.cs文件

using System.Linq;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Views;
using Android.Widget; namespace MyDemos.SrcDemos
{
[Activity(Label = "ch1205NotePadMain")]
public class ch1205NotePadMain : ListActivity
{
// 菜单项
public const int MenuItemDelete = Menu.First;
public const int MenuItemInsert = Menu.First + 1; protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetDefaultKeyMode(DefaultKey.Shortcut);
ListView.SetOnCreateContextMenuListener(this);
PopulateList();
} public void PopulateList()
{
// 获取存放到列表中的所有记事本项
var notes = ch1205NoteRepository.GetAllNotes();
var adapter = new ch1205NoteAdapter(this, this, Resource.Layout.ch1205_Main, notes.ToArray());
ListAdapter = adapter;
} public override bool OnCreateOptionsMenu(IMenu menu)
{
base.OnCreateOptionsMenu(menu);
menu.Add(0, MenuItemInsert, 0, "添加")
.SetShortcut('3', 'a')
.SetIcon(Android.Resource.Drawable.IcMenuAdd);
return true;
} public override bool OnOptionsItemSelected(IMenuItem item)
{
switch (item.ItemId)
{
case MenuItemInsert: // 通过intent添加新项
var intent = new Intent(this, typeof(ch1205NoteEditorActivity));
intent.PutExtra("note_id", -1L);
StartActivityForResult(intent, 0);
return true;
}
return base.OnOptionsItemSelected(item);
} public override void OnCreateContextMenu(IContextMenu menu, View view, IContextMenuContextMenuInfo menuInfo)
{
var info = (AdapterView.AdapterContextMenuInfo)menuInfo;
var note = (ch1205Note)ListAdapter.GetItem(info.Position);
menu.Add(0, MenuItemDelete, 0, "删除");
} public override bool OnContextItemSelected(IMenuItem item)
{
var info = (AdapterView.AdapterContextMenuInfo)item.MenuInfo;
var note = (ch1205Note)ListAdapter.GetItem(info.Position);
switch (item.ItemId)
{
case MenuItemDelete: // 删除该记事本项
ch1205NoteRepository.DeleteNote(note);
PopulateList();
return true;
}
return false;
} protected override void OnListItemClick(ListView l, View v, int position, long id)
{
var selected = (ch1205Note)ListAdapter.GetItem(position);
// 执行activity,查看/编辑当前选中的项
var intent = new Intent(this, typeof(ch1205NoteEditorActivity));
intent.PutExtra("note_id", selected.Id);
StartActivityForResult(intent, 0);
} protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
// 当列表项发生变化时,这里仅关心如何刷新它,并没有处理选定的项
PopulateList();
}
}
}

OK,这一章就讲到这了。

【Android】12.6 利用Intent实现记事本功能(NotePad)的更多相关文章

  1. 【Android基础】利用Intent在Activity之间传递数据

    前言: 上一篇文章给大家聊了Intent的用法,如何用Intent启动Activity和隐式Intent,这一篇文章给大家聊聊如何利用Intent在Activity之间进行沟通.   从一个Activ ...

  2. 【Android】12.5 利用Intent读取和更新通讯录

    分类:C#.Android.VS2015: 创建日期:2016-02-23 修改日期:2016-03-08更正了未关闭cursor的bug.  一.简介 本节演示如何在安卓系统中通过用户配置文件(us ...

  3. 【Android】12.4 利用Intent读取图库中的图片

    分类:C#.Android.VS2015: 创建日期:2016-02-23 一.简介 该示例演示如何从图库(Gallery)中读取图像并用ImageView将它显示出来. 二.示例-ch1203Rea ...

  4. 【Android】12.2 利用Intent启动和关闭Activity

    分类:C#.Android.VS2015: 创建日期:2016-02-23 一.简介 Android应用程序中一般都有多个Activity,在Activity中,通过调用StartActivity方法 ...

  5. Android中,利用Intent传递对象值

    在很多情况下,调用startActivity(Intent) 方法,跳转到另外一个Activity或其他component,需要传递一个对象给它. 可以让这个要传递的对象所属类实现Serializab ...

  6. Android开发值利用Intent进行put传值,setclass启动activity,并用get进行取值

    传值方法一 [java] Intent intent = new Intent(); Bundle bundle = new Bundle(); //该类用作携带数据 bundle.putString ...

  7. Android利用Intent与其他应用交互

    前言: 上一篇博客给大家聊了Intent的定义,分类.属性和功能,相信大家对于Intent在Android中的作用已经清楚,这一篇博客将会给大家聊Intent的用法. Android系统的一个重要特性 ...

  8. Android利用Intent与其它应用交互

    前言: 上一篇博客给大家聊了Intent的定义.分类.属性和功能,相信大家对于Intent在Android中的作用已经清楚,这一篇博客将会给大家聊Intent的使用方法. Android系统的一个重要 ...

  9. android 下 利用webview实现浏览器功能

    android 下 利用webview实现浏览器功能(一): 1.界面添加WEBVIEW控件. 2.在界面.JAVA代码页面(protected void onCreate(Bundle savedI ...

随机推荐

  1. pytest文档11-assert断言

    前言 断言是写自动化测试基本最重要的一步,一个用例没有断言,就失去了自动化测试的意义了.什么是断言呢? 简单来讲就是实际结果和期望结果去对比,符合预期那就测试pass,不符合预期那就测试 failed ...

  2. 角摩网发布在线制作Epub、Mobi格式的电子书

    原来cn的域名没有及时续约被人用了,现在用www.joymo.cc开始新的电子书制作之路. 目前支持Epub和Mobi格式,会陆续加入PDF和APK的电子书.

  3. @使用javap反编译Java字节码文件

    在Sun公司提供的JDK中,就已经内置了Java字节码文件反编译工具javap.exe(位于JDK安装目录的bin文件夹下). 我们可以在dos窗口中使用javap来反汇编指定的Java字节码文件.在 ...

  4. CRF,没完全看懂

    这篇文章,感觉讲的还比较浅显易懂: http://www.sohu.com/a/207085690_206784

  5. C++primer习题--第4章

    本文地址:http://www.cnblogs.com/archimedes/p/cpp-primer-chapter4-ans.html,转载请注明源地址. [习题 4.7] 编写必要的代码将一个数 ...

  6. (转)实现AI中LOD优化技术

    LOD(Level Of Detail)是3D渲染中用到的概念,按照wikipedia上的翻译,可以译为“细节层次”,它是一种根据与观察点的距离,来减低物体或者模型的复杂度来提升渲染效率的优化技术,因 ...

  7. mysql5.5.15配置主从数据库

    1.编辑主库的my.cnf 在[mysqld]下添加如下配置 server-i=1 #一般默认为1,不需要修改(一般都以ip的后两位为server-id,保证全局的一致) read-only=0#主库 ...

  8. function.length和arguments的区别

    function.length:接收到函数体外的参数计算长度 arguments:接收到函数体内的参数计算长度 /** * 函数参数长度和伪数组(arguments)长度不一样! -> 接收到函 ...

  9. cocos2d-x eclipse + NDK 自动编译配置

    文章来自:http://www.cocos2dres.com/view.asp?id=90 1. 准备工作: android NDK    r8版本 ADT Bundle 下载地址:http://de ...

  10. InnerHtml() 与html( )的区别

    InnerHtml() 与html( )的区别 在一个 HTML 文档中, 我们可以使用 .html() 方法来获取任意一个元素的内容. 如果选择器匹配多于一个的元素,那么只有第一个匹配元素的 HTM ...