恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
NotePad功能扩展(2):用MyCursorAdapter与NoteEditor实现NoteColor换肤
首页
资讯中心
/
NotePad功能扩展(2):用MyCursorAdapter与NoteEditor实现NoteColor换肤
NotePad功能扩展(2):用MyCursorAdapter与NoteEditor实现NoteColor换肤
发布时间:2026/10/12 16:39:59
1. 从 NotePad 的「换肤」说起MyCursorAdapter 与 NoteEditor 如何联动Android 自带的 NotePad 示例项目很多人拿它练手。它本身只有标题、正文、创建时间这几个字段列表项是清一色的白底黑字。你如果想给它加一个「笔记背景色」功能让每条笔记在列表里显示不同颜色点进去编辑时编辑区也是这个颜色那就得动三个地方数据库字段、列表适配器、编辑页。我试过直接在noteslist_item.xml里写死背景色结果所有笔记一个样根本没法区分。正确的做法是在NotePad.Notes契约类里加一个COLUMN_NAME_BACK_COLOR字段在colors.xml里定义色值常量然后让MyCursorAdapter在getView()里根据这个字段给每个 item 着色NoteEditor在onResume()里读取同一字段给编辑区着色。这样列表和编辑页读的是同一个数据源颜色自然同步。这篇聚焦的就是这个链路colors.xml定义色值 →MyCursorAdapter绑定颜色 →NoteEditor实时预览 →NoteColor选择器回写数据库。适合已经跑通 NotePad 基础版本、想加一个换肤功能的 Android 开发者。下面按可复制的步骤来每一步都给完整代码。2. 前置准备数据库字段、colors.xml 与 color_select.xml2.1 在 NotePad.Notes 契约类里加颜色字段打开NotePad.java或者你的Notes.java在Columns接口里加public static final String COLUMN_NAME_BACK_COLOR color;然后在NotePad类里定义颜色常量public static final int DEFAULT_COLOR 0; // 白 public static final int YELLOW_COLOR 1; public static final int BLUE_COLOR 2; public static final int GREEN_COLOR 3; public static final int RED_COLOR 4;注意NotePadProvider的onCreate()里建表语句要同步加上color INTEGER否则插入会报no such column: color。如果你不想改数据库版本可以临时用ALTER TABLE在onUpgrade()里加但更干净的做法是直接改CREATE TABLE语句并升版本号。2.2 新建 colors.xml在res/values/下新建colors.xml?xml version1.0 encodingutf-8? resources color namecolor1#be96df/color color namewhite#ffffff/color color nameyellow#fdef90/color color nameblue#6dc1ed/color color namegreen#94e49f/color color namered#f19696/color /resources2.3 新建 color_select.xml 选择器在res/drawable/下新建color_select.xml用于列表项按下时的反馈?xml version1.0 encodingutf-8? selector xmlns:androidhttp://schemas.android.com/apk/res/android item android:drawablecolor/color1 android:state_pressedtrue/ item android:drawablecolor/white/ /selector然后在noteslist_item.xml的根布局或 TextView 上加android:backgrounddrawable/color_select这一步做完列表项默认白底按下时变成#be96df。但这是静态的真正按每条笔记颜色显示还得靠 Adapter。3. MyCursorAdapter把颜色字段绑定到列表项3.1 新建 MyCursorAdapter在NoteList同包下新建MyCursorAdapter.java继承SimpleCursorAdapterpublic class MyCursorAdapter extends SimpleCursorAdapter { private Context mContext; private int mLayout; public MyCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { super(context, layout, c, from, to); this.mContext context; this.mLayout layout; } Override public View getView(int position, View convertView, ViewGroup parent) { View view super.getView(position, convertView, parent); Cursor cursor getCursor(); if (cursor ! null cursor.moveToPosition(position)) { int colorIndex cursor.getColumnIndex( NotePad.Notes.COLUMN_NAME_BACK_COLOR); int color cursor.getInt(colorIndex); switch (color) { case NotePad.Notes.YELLOW_COLOR: view.setBackgroundColor(Color.rgb(247, 216, 133)); break; case NotePad.Notes.BLUE_COLOR: view.setBackgroundColor(Color.rgb(165, 202, 237)); break; case NotePad.Notes.GREEN_COLOR: view.setBackgroundColor(Color.rgb(161, 214, 174)); break; case NotePad.Notes.RED_COLOR: view.setBackgroundColor(Color.rgb(244, 149, 133)); break; default: view.setBackgroundColor(Color.rgb(255, 255, 255)); break; } } return view; } }3.2 在 NoteList 和 NoteSearch 里替换适配器原来NoteList里用的是SimpleCursorAdapter现在改成MyCursorAdapter并且dataColumns和viewIDs要加上颜色字段对应的映射虽然颜色不是直接显示文本但 Cursor 必须查出这一列String[] dataColumns { NotePad.Notes.COLUMN_NAME_TITLE, NotePad.Notes.COLUMN_NAME_BACK_COLOR }; int[] viewIDs { R.id.text1, R.id.text1 }; MyCursorAdapter adapter new MyCursorAdapter( this, R.layout.noteslist_item, cursor, dataColumns, viewIDs ); setListAdapter(adapter);NoteSearch里同理把SimpleCursorAdapter换成MyCursorAdapter。注意PROJECTION里要加上COLUMN_NAME_BACK_COLOR否则getColumnIndex返回 -1取色会崩。3.3 一个容易忽略的点SimpleCursorAdapter的getView()内部会复用convertView如果你在getView()里直接setBackgroundColor滚动时可能出现颜色错乱。上面的写法每次都会根据当前 position 重新取色所以没问题。但如果你在bindView()里做就要注意cursor.moveToPosition(position)的调用时机。4. NoteEditor编辑页实时预览与保存4.1 在 PROJECTION 里加颜色字段打开NoteEditor.java找到PROJECTIONprivate static final String[] PROJECTION new String[] { NotePad.Notes._ID, NotePad.Notes.COLUMN_NAME_TITLE, NotePad.Notes.COLUMN_NAME_NOTE, NotePad.Notes.COLUMN_NAME_BACK_COLOR };4.2 在 onResume() 里读取颜色并着色Override protected void onResume() { super.onResume(); if (mCursor ! null) { mCursor.moveToFirst(); int x mCursor.getColumnIndex(NotePad.Notes.COLUMN_NAME_BACK_COLOR); int y mCursor.getInt(x); Log.i(NoteEditor, color y); switch (y) { case NotePad.Notes.YELLOW_COLOR: mText.setBackgroundColor(Color.rgb(247, 216, 133)); break; case NotePad.Notes.BLUE_COLOR: mText.setBackgroundColor(Color.rgb(165, 202, 237)); break; case NotePad.Notes.GREEN_COLOR: mText.setBackgroundColor(Color.rgb(161, 214, 174)); break; case NotePad.Notes.RED_COLOR: mText.setBackgroundColor(Color.rgb(244, 149, 133)); break; default: mText.setBackgroundColor(Color.rgb(255, 255, 255)); break; } } }mText就是编辑区的EditText。这样从列表点进编辑页编辑区背景色和列表项一致。4.3 在菜单里加「更改背景」入口在res/menu/editor_options_menu.xml里加item android:idid/menu_color android:titlecolor android:icondrawable/ic_menu_edit android:showAsActionalways/然后在NoteEditor的onOptionsItemSelected()里加case R.id.menu_color: Intent intent new Intent(null, mUri); intent.setClass(NoteEditor.this, NoteColor.class); NoteEditor.this.startActivity(intent); break;mUri是当前笔记的 Uri传给NoteColor用于回写。5. NoteColor选择颜色并回写数据库5.1 新建 note_color.xml在res/layout/下新建?xml version1.0 encodingutf-8? LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/android android:layout_widthmatch_parent android:layout_heightwrap_content android:orientationhorizontal ImageButton android:idid/color_white android:layout_width0dp android:layout_height50dp android:layout_weight1 android:background#ffffff android:onClickwhite/ ImageButton android:idid/color_yellow android:layout_width0dp android:layout_height50dp android:layout_weight1 android:background#fdef90 android:onClickyellow/ ImageButton android:idid/color_blue android:layout_width0dp android:layout_height50dp android:layout_weight1 android:background#6dc1ed android:onClickblue/ ImageButton android:idid/color_green android:layout_width0dp android:layout_height50dp android:layout_weight1 android:background#94e49f android:onClickgreen/ ImageButton android:idid/color_red android:layout_width0dp android:layout_height50dp android:layout_weight1 android:background#f19696 android:onClickred/ /LinearLayout5.2 新建 NoteColor.javapublic class NoteColor extends Activity { private Cursor mCursor; private Uri mUri; private int color; private static final String[] PROJECTION new String[] { NotePad.Notes._ID, NotePad.Notes.COLUMN_NAME_BACK_COLOR, }; Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.note_color); mUri getIntent().getData(); mCursor managedQuery(mUri, PROJECTION, null, null, null); } Override protected void onResume() { super.onResume(); if (mCursor.moveToFirst()) { color mCursor.getInt( mCursor.getColumnIndex(NotePad.Notes.COLUMN_NAME_BACK_COLOR)); Log.i(NoteColor, before color); } } Override protected void onPause() { super.onPause(); ContentValues values new ContentValues(); values.put(NotePad.Notes.COLUMN_NAME_BACK_COLOR, color); getContentResolver().update(mUri, values, null, null); Log.i(NoteColor, cun color); } public void white(View view) { color NotePad.Notes.DEFAULT_COLOR; finish(); } public void yellow(View view) { color NotePad.Notes.YELLOW_COLOR; finish(); } public void blue(View view) { color NotePad.Notes.BLUE_COLOR; finish(); } public void green(View view) { color NotePad.Notes.GREEN_COLOR; finish(); } public void red(View view) { color NotePad.Notes.RED_COLOR; finish(); } }5.3 在 AndroidManifest.xml 里注册activity android:nameNoteColor android:themeandroid:style/Theme.Holo.Light.Dialog android:labelSelect Color/用 Dialog 主题选色时弹窗体验更顺。6. 验证新增颜色后列表与编辑页同步生效6.1 验证步骤编译运行进入 NoteList长按菜单新建一条笔记标题随便写正文写点内容。点进这条笔记按菜单键点「color」弹出选色框。选红色finish()回到编辑页。此时onResume()触发编辑区背景应该变成#f49485。返回列表这条笔记的背景色应该也是红色。再点进去编辑区还是红色说明数据库回写成功。6.2 常见报错排查报错 1no such column: color原因NotePadProvider的建表语句没加color字段。解决在onCreate()的CREATE TABLE里加color INTEGER并升数据库版本号。报错 2CursorIndexOutOfBoundsException原因PROJECTION里没加COLUMN_NAME_BACK_COLOR但代码里getColumnIndex取了。解决检查NoteList、NoteSearch、NoteEditor三处的PROJECTION是否都加上了。报错 3列表颜色错乱原因getView()里没有每次重新取色或者cursor.moveToPosition(position)没调用。解决按第 3 节的写法每次getView都moveToPosition后取色。报错 4选色后编辑页没变原因NoteEditor的onResume()里没重新读 Cursor或者mCursor为 null。解决确保onResume()里先mCursor.moveToFirst()再取色。6.3 一次实测记录我在模拟器上跑了一遍新建笔记 → 选蓝色 → 返回列表列表项背景是#a5caed再点进去编辑区也是这个色。Logcat 里看到NoteColor: cun2和NoteEditor: color2说明回写和读取都正常。唯一要注意的是managedQuery在 API 11 以后被标记 deprecated但 NotePad 示例本身就用它不影响运行。如果你想让选色框更紧凑可以把ImageButton的layout_height改成40dplayout_weight保持 1五个按钮平分宽度。另外color_select.xml里的按下色#be96df和实际笔记色是两回事前者是触摸反馈后者是数据驱动别搞混。最后一步如果你在NoteSearch里也换了MyCursorAdapter记得搜索结果的PROJECTION同样要加COLUMN_NAME_BACK_COLOR否则搜索列表里颜色取不到会全部走 default 白色。这个坑我踩过查了半天才发现是NoteSearch的PROJECTION漏了字段。