@ -50,6 +50,7 @@ import android.view.View.OnClickListener;
import android.view.View.OnCreateContextMenuListener ;
import android.view.View.OnTouchListener ;
import android.view.KeyEvent ;
import android.view.ViewGroup ;
import android.view.inputmethod.EditorInfo ;
import android.view.inputmethod.InputMethodManager ;
import android.widget.AdapterView ;
@ -62,8 +63,12 @@ import android.widget.ImageView;
import android.widget.LinearLayout ;
import android.widget.ListView ;
import android.widget.PopupMenu ;
import android.widget.RelativeLayout ;
import android.widget.TextView ;
import android.widget.Toast ;
import android.widget.GridView ;
import android.widget.BaseAdapter ;
import android.view.ViewGroup ;
import net.micode.notes.R ;
import net.micode.notes.data.Notes ;
@ -96,11 +101,23 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private static final int MENU_FOLDER_CHANGE_NAME = 2 ;
private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction" ;
private static final String PREFERENCE_BACKGROUND = "net.micode.notes.background" ;
private static final String BACKGROUND_TYPE_DEFAULT = "default" ;
private static final String BACKGROUND_TYPE_ALBUM = "album" ;
private static final int REQUEST_CODE_PICK_IMAGE = 105 ;
private enum ListEditState {
NOTE_LIST , SUB_FOLDER , CALL_RECORD_FOLDER
} ;
// 背景选项
private static final String [ ] BACKGROUND_OPTIONS = {
"高山流水" , "风中树叶" , "长河落日"
} ;
private static final int [ ] BACKGROUND_RESOURCES = {
R . drawable . background_mountain , R . drawable . background_leaves , R . drawable . background_sunset
} ;
private ListEditState mState ;
private BackgroundQueryHandler mBackgroundQueryHandler ;
@ -110,6 +127,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private ListView mNotesListView ;
private Button mAddNewNote ;
private Button mPrivacyBackButton ;
private boolean mDispatch ;
@ -135,6 +153,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns . TYPE + "<>" + Notes . TYPE_SYSTEM + " AND " + NoteColumns . TYPE + "<>" + Notes . TYPE_TODO + " AND " + NoteColumns . PARENT_ID + "=?) OR (" + NoteColumns . ID + "=" + Notes . ID_CALL_RECORD_FOLDER + " AND " + NoteColumns . NOTES_COUNT + ">0)" ;
// 隐私空间相关常量
private static final int REQUEST_CODE_PRIVACY_SPACE = 104 ;
private String mCurrentPrivacySpaceId = "" ;
private final static int REQUEST_CODE_OPEN_NODE = 102 ;
private final static int REQUEST_CODE_NEW_NODE = 103 ;
@ -146,11 +168,30 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private String mSearchQuery ;
private boolean mIsSearching ;
// 背景相关变量
private View mRootView ;
private RelativeLayout mBackgroundContainer ;
private LinearLayout mMainContent ;
private String mCurrentBackgroundType = BACKGROUND_TYPE_DEFAULT ;
private int mCurrentBackgroundResource = R . drawable . list_background ;
private String mCurrentBackgroundPath = "" ;
@Override
protected void onCreate ( Bundle savedInstanceState ) {
super . onCreate ( savedInstanceState ) ;
setContentView ( R . layout . note_list ) ;
// 获取隐私空间ID
Intent intent = getIntent ( ) ;
if ( intent ! = null ) {
mCurrentPrivacySpaceId = intent . getStringExtra ( "privacy_space_id" ) ;
if ( mCurrentPrivacySpaceId = = null ) {
mCurrentPrivacySpaceId = "" ;
}
}
initResources ( ) ;
initBackground ( ) ;
/ * *
* Insert an introduction when user firstly use this application
@ -160,9 +201,36 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
@Override
protected void onActivityResult ( int requestCode , int resultCode , Intent data ) {
if ( resultCode = = RESULT_OK
& & ( requestCode = = REQUEST_CODE_OPEN_NODE | | requestCode = = REQUEST_CODE_NEW_NODE ) ) {
mNotesListAdapter . changeCursor ( null ) ;
if ( resultCode = = RESULT_OK ) {
if ( requestCode = = REQUEST_CODE_OPEN_NODE | | requestCode = = REQUEST_CODE_NEW_NODE ) {
mNotesListAdapter . changeCursor ( null ) ;
} else if ( requestCode = = REQUEST_CODE_PRIVACY_SPACE ) {
// 处理从隐私空间返回的结果
if ( data ! = null ) {
String privacySpaceId = data . getStringExtra ( "privacy_space_id" ) ;
if ( ! TextUtils . isEmpty ( privacySpaceId ) ) {
mCurrentPrivacySpaceId = privacySpaceId ;
updatePrivacySpaceUI ( ) ;
startAsyncNotesListQuery ( ) ;
}
}
} else if ( requestCode = = REQUEST_CODE_PICK_IMAGE ) {
// 处理从相册选择图片的结果
if ( data ! = null & & data . getData ( ) ! = null ) {
try {
// 保存图片路径
mCurrentBackgroundType = BACKGROUND_TYPE_ALBUM ;
mCurrentBackgroundPath = data . getData ( ) . toString ( ) ;
// 更新背景
updateBackground ( ) ;
// 保存设置
saveBackgroundSetting ( ) ;
} catch ( Exception e ) {
e . printStackTrace ( ) ;
Toast . makeText ( this , "图片加载失败" , Toast . LENGTH_SHORT ) . show ( ) ;
}
}
}
} else {
super . onActivityResult ( requestCode , resultCode , data ) ;
}
@ -290,13 +358,46 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mAddNewNote = ( Button ) findViewById ( R . id . btn_add_note ) ;
mAddNewNote . setOnClickListener ( this ) ;
mAddNewNote . setOnTouchListener ( new NewNoteOnTouchListener ( ) ) ;
mPrivacyBackButton = ( Button ) findViewById ( R . id . btn_privacy_back ) ;
mPrivacyBackButton . setOnClickListener ( this ) ;
mDispatch = false ;
mDispatchY = 0 ;
mOriginY = 0 ;
mTitleBar = ( TextView ) findViewById ( R . id . tv_title_bar ) ;
mMainContent = ( LinearLayout ) findViewById ( R . id . main_content ) ;
// 获取根视图作为背景容器
mBackgroundContainer = ( RelativeLayout ) findViewById ( R . id . note_list_root ) ;
if ( mBackgroundContainer = = null ) {
// 如果找不到, 使用content view
View contentView = getWindow ( ) . getDecorView ( ) . findViewById ( android . R . id . content ) ;
if ( contentView instanceof ViewGroup ) {
ViewGroup contentViewGroup = ( ViewGroup ) contentView ;
if ( contentViewGroup . getChildCount ( ) > 0 ) {
View childView = contentViewGroup . getChildAt ( 0 ) ;
if ( childView instanceof RelativeLayout ) {
mBackgroundContainer = ( RelativeLayout ) childView ;
}
}
}
}
// 最后的备用方案
if ( mBackgroundContainer = = null ) {
// 如果还是找不到,使用整个窗口的装饰视图作为背景容器
mBackgroundContainer = new RelativeLayout ( this ) ;
ViewGroup decorView = ( ViewGroup ) getWindow ( ) . getDecorView ( ) ;
View contentView = decorView . findViewById ( android . R . id . content ) ;
if ( contentView ! = null ) {
decorView . removeView ( contentView ) ;
mBackgroundContainer . addView ( contentView ) ;
decorView . addView ( mBackgroundContainer ) ;
}
}
mState = ListEditState . NOTE_LIST ;
mModeCallBack = new ModeCallback ( ) ;
// 检查是否处于隐私空间中
updatePrivacySpaceUI ( ) ;
// 初始化界面切换栏
mNotesTab = ( TextView ) findViewById ( R . id . notes_tab ) ;
mTodoTab = ( TextView ) findViewById ( R . id . todo_tab ) ;
@ -711,6 +812,57 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
// 添加隐私空间筛选条件
if ( ! TextUtils . isEmpty ( mCurrentPrivacySpaceId ) ) {
// 在隐私空间中,只显示该隐私空间的便签
String privacyCondition = NoteColumns . PRIVACY_SPACE_ID + "=?" ;
if ( mCurrentFolderId = = Notes . ID_ROOT_FOLDER ) {
// 根文件夹需要特殊处理
if ( ! TextUtils . isEmpty ( mSearchQuery ) | | ! TextUtils . isEmpty ( mSelectedTag ) ) {
// 有搜索关键词或标签的情况
baseSelection = "(" + baseSelection + ") AND " + privacyCondition ;
} else {
// 没有搜索关键词和标签的情况
baseSelection = "(" + NoteColumns . TYPE + "<>" + Notes . TYPE_SYSTEM + " AND " + NoteColumns . PARENT_ID + "=? AND " + privacyCondition + ")" ;
// 重新构建参数列表
argsList . clear ( ) ;
argsList . add ( String . valueOf ( mCurrentFolderId ) ) ;
argsList . add ( mCurrentPrivacySpaceId ) ;
}
} else {
// 普通文件夹
if ( ! TextUtils . isEmpty ( mSearchQuery ) | | ! TextUtils . isEmpty ( mSelectedTag ) ) {
// 有搜索关键词或标签的情况
baseSelection = "(" + baseSelection + ") AND " + privacyCondition ;
} else {
// 没有搜索关键词和标签的情况
baseSelection = NoteColumns . PARENT_ID + "=? AND " + NoteColumns . TYPE + "<>" + Notes . TYPE_TODO + " AND " + privacyCondition ;
// 重新构建参数列表
argsList . clear ( ) ;
argsList . add ( String . valueOf ( mCurrentFolderId ) ) ;
argsList . add ( mCurrentPrivacySpaceId ) ;
}
}
if ( ! TextUtils . isEmpty ( mSearchQuery ) | | ! TextUtils . isEmpty ( mSelectedTag ) ) {
// 有搜索关键词或标签的情况, 需要添加隐私空间ID参数
argsList . add ( mCurrentPrivacySpaceId ) ;
}
} else {
// 不在隐私空间中,只显示非隐私空间的便签
String privacyCondition = "(" + NoteColumns . PRIVACY_SPACE_ID + "='' OR " + NoteColumns . PRIVACY_SPACE_ID + " IS NULL)" ;
if ( mCurrentFolderId = = Notes . ID_ROOT_FOLDER ) {
// 根文件夹需要特殊处理
baseSelection = "(" + baseSelection + ") AND " + privacyCondition ;
} else {
// 普通文件夹
if ( baseSelection . contains ( "AND" ) ) {
baseSelection + = " AND " + privacyCondition ;
} else {
baseSelection + = " WHERE " + privacyCondition ;
}
}
}
selection = baseSelection ;
selectionArgs = argsList . toArray ( new String [ argsList . size ( ) ] ) ;
@ -769,6 +921,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
Intent intent = new Intent ( this , NoteEditActivity . class ) ;
intent . setAction ( Intent . ACTION_INSERT_OR_EDIT ) ;
intent . putExtra ( Notes . INTENT_EXTRA_FOLDER_ID , mCurrentFolderId ) ;
intent . putExtra ( "privacy_space_id" , mCurrentPrivacySpaceId ) ;
this . startActivityForResult ( intent , REQUEST_CODE_NEW_NODE ) ;
}
@ -856,6 +1009,29 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
public void onClick ( View v ) {
if ( v . getId ( ) = = R . id . btn_add_note ) {
createNewNote ( ) ;
} else if ( v . getId ( ) = = R . id . btn_privacy_back ) {
// 从隐私空间返回普通空间
mCurrentPrivacySpaceId = "" ;
updatePrivacySpaceUI ( ) ;
startAsyncNotesListQuery ( ) ;
}
}
/ * *
* 更 新 隐 私 空 间 相 关 的 UI 元 素
* /
private void updatePrivacySpaceUI ( ) {
if ( ! TextUtils . isEmpty ( mCurrentPrivacySpaceId ) ) {
// 在隐私空间中,显示隐私空间名称
mTitleBar . setText ( "隐私空间" ) ;
mTitleBar . setVisibility ( View . VISIBLE ) ;
// 显示隐私空间返回按钮
mPrivacyBackButton . setVisibility ( View . VISIBLE ) ;
} else {
// 不在隐私空间中,隐藏标题栏或显示默认标题
mTitleBar . setVisibility ( View . GONE ) ;
// 隐藏隐私空间返回按钮
mPrivacyBackButton . setVisibility ( View . GONE ) ;
}
}
@ -1060,6 +1236,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
// set sync or sync_cancel
menu . findItem ( R . id . menu_sync ) . setTitle (
GTaskSyncService . isSyncing ( ) ? R . string . menu_sync_cancel : R . string . menu_sync ) ;
// 添加背景设置选项
addBackgroundMenuItems ( menu ) ;
} else if ( mState = = ListEditState . SUB_FOLDER ) {
getMenuInflater ( ) . inflate ( R . menu . sub_folder , menu ) ;
} else if ( mState = = ListEditState . CALL_RECORD_FOLDER ) {
@ -1094,6 +1272,19 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
onSearchRequested ( ) ;
} else if ( item . getItemId ( ) = = R . id . menu_trash ) {
startTrashActivity ( ) ;
} else if ( item . getItemId ( ) = = R . id . menu_privacy_space ) {
if ( ! TextUtils . isEmpty ( mCurrentPrivacySpaceId ) ) {
// 从隐私空间返回普通空间
Intent intent = new Intent ( this , NotesListActivity . class ) ;
intent . putExtra ( "privacy_space_id" , "" ) ;
intent . setFlags ( Intent . FLAG_ACTIVITY_CLEAR_TOP | Intent . FLAG_ACTIVITY_NEW_TASK ) ;
startActivity ( intent ) ;
finish ( ) ;
} else {
// 打开隐私空间
Intent intent = new Intent ( this , PrivacySpaceActivity . class ) ;
startActivityForResult ( intent , REQUEST_CODE_PRIVACY_SPACE ) ;
}
}
return true ;
}
@ -1413,4 +1604,150 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
builder . show ( ) ;
}
/ * *
* 初 始 化 背 景
* /
private void initBackground ( ) {
// 加载保存的背景设置
SharedPreferences sp = PreferenceManager . getDefaultSharedPreferences ( this ) ;
mCurrentBackgroundType = sp . getString ( PREFERENCE_BACKGROUND + "_type" , BACKGROUND_TYPE_DEFAULT ) ;
mCurrentBackgroundPath = sp . getString ( PREFERENCE_BACKGROUND + "_path" , "" ) ;
if ( BACKGROUND_TYPE_DEFAULT . equals ( mCurrentBackgroundType ) ) {
int backgroundIndex = sp . getInt ( PREFERENCE_BACKGROUND + "_index" , 0 ) ;
if ( backgroundIndex > = 0 & & backgroundIndex < BACKGROUND_RESOURCES . length ) {
mCurrentBackgroundResource = BACKGROUND_RESOURCES [ backgroundIndex ] ;
}
}
// 更新背景
updateBackground ( ) ;
}
/ * *
* 更 新 背 景
* /
private void updateBackground ( ) {
if ( mBackgroundContainer = = null ) {
return ;
}
try {
if ( BACKGROUND_TYPE_DEFAULT . equals ( mCurrentBackgroundType ) ) {
// 使用默认背景
mBackgroundContainer . setBackgroundResource ( mCurrentBackgroundResource ) ;
} else if ( BACKGROUND_TYPE_ALBUM . equals ( mCurrentBackgroundType ) & & ! TextUtils . isEmpty ( mCurrentBackgroundPath ) ) {
// 使用相册图片作为背景
try {
android . graphics . Bitmap bitmap = android . graphics . BitmapFactory . decodeStream (
getContentResolver ( ) . openInputStream ( android . net . Uri . parse ( mCurrentBackgroundPath ) ) ) ;
if ( bitmap ! = null ) {
// 计算屏幕尺寸
android . util . DisplayMetrics displayMetrics = new android . util . DisplayMetrics ( ) ;
getWindowManager ( ) . getDefaultDisplay ( ) . getMetrics ( displayMetrics ) ;
int screenWidth = displayMetrics . widthPixels ;
int screenHeight = displayMetrics . heightPixels ;
// 缩放图片以适配屏幕
android . graphics . Bitmap scaledBitmap = android . graphics . Bitmap . createScaledBitmap (
bitmap , screenWidth , screenHeight , true ) ;
android . graphics . drawable . BitmapDrawable drawable = new android . graphics . drawable . BitmapDrawable ( getResources ( ) , scaledBitmap ) ;
// 设置背景图片的缩放方式
drawable . setTileModeXY ( android . graphics . Shader . TileMode . CLAMP , android . graphics . Shader . TileMode . CLAMP ) ;
mBackgroundContainer . setBackground ( drawable ) ;
// 释放原始 bitmap
if ( bitmap ! = scaledBitmap ) {
bitmap . recycle ( ) ;
}
}
} catch ( Exception e ) {
e . printStackTrace ( ) ;
Toast . makeText ( this , "图片加载失败" , Toast . LENGTH_SHORT ) . show ( ) ;
// 加载失败时使用默认背景
mBackgroundContainer . setBackgroundResource ( R . drawable . list_background ) ;
}
}
} catch ( Exception e ) {
e . printStackTrace ( ) ;
// 加载失败时使用默认背景
mBackgroundContainer . setBackgroundResource ( R . drawable . list_background ) ;
}
}
/ * *
* 保 存 背 景 设 置
* /
private void saveBackgroundSetting ( ) {
SharedPreferences sp = PreferenceManager . getDefaultSharedPreferences ( this ) ;
SharedPreferences . Editor editor = sp . edit ( ) ;
editor . putString ( PREFERENCE_BACKGROUND + "_type" , mCurrentBackgroundType ) ;
editor . putString ( PREFERENCE_BACKGROUND + "_path" , mCurrentBackgroundPath ) ;
if ( BACKGROUND_TYPE_DEFAULT . equals ( mCurrentBackgroundType ) ) {
// 找到当前背景资源的索引
int index = 0 ;
for ( int i = 0 ; i < BACKGROUND_RESOURCES . length ; i + + ) {
if ( BACKGROUND_RESOURCES [ i ] = = mCurrentBackgroundResource ) {
index = i ;
break ;
}
}
editor . putInt ( PREFERENCE_BACKGROUND + "_index" , index ) ;
}
editor . apply ( ) ;
}
/ * *
* 显 示 背 景 选 择 对 话 框
* /
private void showBackgroundSelectorDialog ( ) {
AlertDialog . Builder builder = new AlertDialog . Builder ( this ) ;
builder . setTitle ( "选择背景" ) ;
// 创建背景选项数组,添加从相册选择的选项
String [ ] options = new String [ BACKGROUND_OPTIONS . length + 1 ] ;
System . arraycopy ( BACKGROUND_OPTIONS , 0 , options , 0 , BACKGROUND_OPTIONS . length ) ;
options [ BACKGROUND_OPTIONS . length ] = "从相册选择" ;
builder . setItems ( options , new DialogInterface . OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
if ( which < BACKGROUND_OPTIONS . length ) {
// 选择预设背景
mCurrentBackgroundType = BACKGROUND_TYPE_DEFAULT ;
mCurrentBackgroundResource = BACKGROUND_RESOURCES [ which ] ;
mCurrentBackgroundPath = "" ;
updateBackground ( ) ;
saveBackgroundSetting ( ) ;
Toast . makeText ( NotesListActivity . this , "背景已更新" , Toast . LENGTH_SHORT ) . show ( ) ;
} else {
// 从相册选择
Intent intent = new Intent ( Intent . ACTION_GET_CONTENT ) ;
intent . setType ( "image/*" ) ;
intent . addCategory ( Intent . CATEGORY_OPENABLE ) ;
startActivityForResult ( intent , REQUEST_CODE_PICK_IMAGE ) ;
}
}
} ) ;
builder . show ( ) ;
}
/ * *
* 在 菜 单 中 添 加 背 景 设 置 选 项
* /
private void addBackgroundMenuItems ( Menu menu ) {
MenuItem backgroundMenu = menu . add ( 0 , 100 , 0 , "背景设置" ) ;
backgroundMenu . setOnMenuItemClickListener ( new OnMenuItemClickListener ( ) {
@Override
public boolean onMenuItemClick ( MenuItem item ) {
showBackgroundSelectorDialog ( ) ;
return true ;
}
} ) ;
}
}