|
|
|
|
@ -55,11 +55,14 @@ import android.widget.AdapterView.OnItemClickListener;
|
|
|
|
|
import android.widget.AdapterView.OnItemLongClickListener;
|
|
|
|
|
import android.widget.Button;
|
|
|
|
|
import android.widget.EditText;
|
|
|
|
|
import android.widget.ListView;
|
|
|
|
|
import android.widget.PopupMenu;
|
|
|
|
|
import android.widget.TextView;
|
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
|
|
|
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
|
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
|
import androidx.recyclerview.widget.DefaultItemAnimator;
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.R;
|
|
|
|
|
import net.micode.notes.data.Notes;
|
|
|
|
|
import net.micode.notes.data.Notes.NoteColumns;
|
|
|
|
|
@ -68,7 +71,7 @@ import net.micode.notes.model.WorkingNote;
|
|
|
|
|
import net.micode.notes.tool.BackupUtils;
|
|
|
|
|
import net.micode.notes.tool.DataUtils;
|
|
|
|
|
import net.micode.notes.tool.ResourceParser;
|
|
|
|
|
import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute;
|
|
|
|
|
import net.micode.notes.ui.NotesRecyclerViewAdapter.AppWidgetAttribute;
|
|
|
|
|
import net.micode.notes.widget.NoteWidgetProvider_2x;
|
|
|
|
|
import net.micode.notes.widget.NoteWidgetProvider_4x;
|
|
|
|
|
|
|
|
|
|
@ -96,7 +99,7 @@ import java.util.HashSet;
|
|
|
|
|
* @see NotesListAdapter
|
|
|
|
|
* @see GTaskSyncService
|
|
|
|
|
*/
|
|
|
|
|
public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
|
|
|
|
|
public class NotesListActivity extends Activity implements OnClickListener, NotesRecyclerViewAdapter.OnItemLongClickListener {
|
|
|
|
|
// 笔记列表查询令牌
|
|
|
|
|
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
|
|
|
|
|
|
|
|
|
|
@ -133,10 +136,16 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
private BackgroundQueryHandler mBackgroundQueryHandler;
|
|
|
|
|
|
|
|
|
|
// 笔记列表适配器
|
|
|
|
|
private NotesListAdapter mNotesListAdapter;
|
|
|
|
|
private NotesRecyclerViewAdapter mNotesListAdapter;
|
|
|
|
|
|
|
|
|
|
// 笔记列表视图
|
|
|
|
|
private ListView mNotesListView;
|
|
|
|
|
private RecyclerView mNotesRecyclerView;
|
|
|
|
|
|
|
|
|
|
// 布局管理器
|
|
|
|
|
private LinearLayoutManager mLayoutManager;
|
|
|
|
|
|
|
|
|
|
// 布局切换控制器
|
|
|
|
|
private LayoutManagerController mLayoutManagerController;
|
|
|
|
|
|
|
|
|
|
// 新建笔记按钮
|
|
|
|
|
private Button mAddNewNote;
|
|
|
|
|
@ -216,7 +225,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
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);
|
|
|
|
|
mNotesListAdapter.swapCursor(null);
|
|
|
|
|
} else {
|
|
|
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
|
|
|
}
|
|
|
|
|
@ -293,13 +302,43 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
mContentResolver = this.getContentResolver();
|
|
|
|
|
mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver());
|
|
|
|
|
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
|
|
|
|
|
mNotesListView = (ListView) findViewById(R.id.notes_list);
|
|
|
|
|
mNotesListView.addFooterView(LayoutInflater.from(this).inflate(R.layout.note_list_footer, null),
|
|
|
|
|
null, false);
|
|
|
|
|
mNotesListView.setOnItemClickListener(new OnListItemClickListener());
|
|
|
|
|
mNotesListView.setOnItemLongClickListener(this);
|
|
|
|
|
mNotesListAdapter = new NotesListAdapter(this);
|
|
|
|
|
mNotesListView.setAdapter(mNotesListAdapter);
|
|
|
|
|
mNotesRecyclerView = (RecyclerView) findViewById(R.id.notes_list);
|
|
|
|
|
mLayoutManager = new LinearLayoutManager(this);
|
|
|
|
|
mNotesRecyclerView.setLayoutManager(mLayoutManager);
|
|
|
|
|
|
|
|
|
|
// 创建适配器
|
|
|
|
|
mNotesListAdapter = new NotesRecyclerViewAdapter(this);
|
|
|
|
|
mNotesRecyclerView.setAdapter(mNotesListAdapter);
|
|
|
|
|
|
|
|
|
|
// 设置动画
|
|
|
|
|
DefaultItemAnimator animator = new DefaultItemAnimator();
|
|
|
|
|
animator.setAddDuration(300);
|
|
|
|
|
animator.setRemoveDuration(300);
|
|
|
|
|
animator.setMoveDuration(300);
|
|
|
|
|
animator.setChangeDuration(300);
|
|
|
|
|
mNotesRecyclerView.setItemAnimator(animator);
|
|
|
|
|
|
|
|
|
|
// 初始化布局切换控制器
|
|
|
|
|
mLayoutManagerController = new LayoutManagerController(this, mNotesRecyclerView,
|
|
|
|
|
new LayoutManagerController.LayoutChangeListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onLayoutChanged(LayoutType newLayoutType) {
|
|
|
|
|
showToast("已切换到" + newLayoutType.getDisplayName());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onLayoutChangeFailed(Exception e) {
|
|
|
|
|
showToast("布局切换失败: " + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 应用保存的布局
|
|
|
|
|
mLayoutManagerController.initializeLayout();
|
|
|
|
|
|
|
|
|
|
// 设置点击和长按监听
|
|
|
|
|
mNotesListAdapter.setOnItemClickListener(new OnListItemClickListener());
|
|
|
|
|
mNotesListAdapter.setOnItemLongClickListener(this);
|
|
|
|
|
|
|
|
|
|
mAddNewNote = (Button) findViewById(R.id.btn_new_note);
|
|
|
|
|
mAddNewNote.setOnClickListener(this);
|
|
|
|
|
mAddNewNote.setOnTouchListener(new NewNoteOnTouchListener());
|
|
|
|
|
@ -314,9 +353,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
/**
|
|
|
|
|
* 多选模式回调类
|
|
|
|
|
*
|
|
|
|
|
* 实现ListView.MultiChoiceModeListener接口,处理多选模式的创建、销毁和项选中状态变化
|
|
|
|
|
* 实现ActionMode.Callback接口,处理多选模式的创建、销毁和项选中状态变化
|
|
|
|
|
*/
|
|
|
|
|
private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener {
|
|
|
|
|
private class ModeCallback implements ActionMode.Callback, OnMenuItemClickListener {
|
|
|
|
|
private DropdownMenu mDropDownMenu;
|
|
|
|
|
private ActionMode mActionMode;
|
|
|
|
|
private MenuItem mMoveMenu;
|
|
|
|
|
@ -341,7 +380,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
}
|
|
|
|
|
mActionMode = mode;
|
|
|
|
|
mNotesListAdapter.setChoiceMode(true);
|
|
|
|
|
mNotesListView.setLongClickable(false);
|
|
|
|
|
mAddNewNote.setVisibility(View.GONE);
|
|
|
|
|
|
|
|
|
|
View customView = LayoutInflater.from(NotesListActivity.this).inflate(
|
|
|
|
|
@ -422,7 +460,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
*/
|
|
|
|
|
public void onDestroyActionMode(ActionMode mode) {
|
|
|
|
|
mNotesListAdapter.setChoiceMode(false);
|
|
|
|
|
mNotesListView.setLongClickable(true);
|
|
|
|
|
mAddNewNote.setVisibility(View.VISIBLE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -510,15 +547,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
* also change. This is very bad, just for the UI designer's strong requirement.
|
|
|
|
|
*/
|
|
|
|
|
if (event.getY() < (event.getX() * (-0.12) + 94)) {
|
|
|
|
|
View view = mNotesListView.getChildAt(mNotesListView.getChildCount() - 1
|
|
|
|
|
- mNotesListView.getFooterViewsCount());
|
|
|
|
|
View view = mNotesRecyclerView.getChildAt(mNotesRecyclerView.getChildCount() - 1);
|
|
|
|
|
if (view != null && view.getBottom() > start
|
|
|
|
|
&& (view.getTop() < (start + 94))) {
|
|
|
|
|
mOriginY = (int) event.getY();
|
|
|
|
|
mDispatchY = eventY;
|
|
|
|
|
event.setLocation(event.getX(), mDispatchY);
|
|
|
|
|
mDispatch = true;
|
|
|
|
|
return mNotesListView.dispatchTouchEvent(event);
|
|
|
|
|
return mNotesRecyclerView.dispatchTouchEvent(event);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
@ -527,7 +563,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
if (mDispatch) {
|
|
|
|
|
mDispatchY += (int) event.getY() - mOriginY;
|
|
|
|
|
event.setLocation(event.getX(), mDispatchY);
|
|
|
|
|
return mNotesListView.dispatchTouchEvent(event);
|
|
|
|
|
return mNotesRecyclerView.dispatchTouchEvent(event);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@ -535,7 +571,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
if (mDispatch) {
|
|
|
|
|
event.setLocation(event.getX(), mDispatchY);
|
|
|
|
|
mDispatch = false;
|
|
|
|
|
return mNotesListView.dispatchTouchEvent(event);
|
|
|
|
|
return mNotesRecyclerView.dispatchTouchEvent(event);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@ -594,7 +630,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
|
|
|
|
|
switch (token) {
|
|
|
|
|
case FOLDER_NOTE_LIST_QUERY_TOKEN:
|
|
|
|
|
mNotesListAdapter.changeCursor(cursor);
|
|
|
|
|
mNotesListAdapter.swapCursor(cursor);
|
|
|
|
|
break;
|
|
|
|
|
case FOLDER_LIST_QUERY_TOKEN:
|
|
|
|
|
if (cursor != null && cursor.getCount() > 0) {
|
|
|
|
|
@ -979,9 +1015,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onContextMenuClosed(Menu menu) {
|
|
|
|
|
if (mNotesListView != null) {
|
|
|
|
|
mNotesListView.setOnCreateContextMenuListener(null);
|
|
|
|
|
}
|
|
|
|
|
super.onContextMenuClosed(menu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1100,6 +1133,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
case R.id.menu_search:
|
|
|
|
|
onSearchRequested();
|
|
|
|
|
break;
|
|
|
|
|
case R.id.menu_switch_layout:
|
|
|
|
|
showLayoutSettingsDialog();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@ -1168,6 +1204,28 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
}.execute();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 显示布局设置对话框
|
|
|
|
|
* <p>
|
|
|
|
|
* 打开布局设置对话框,允许用户选择布局类型、网格列数和项目间距。
|
|
|
|
|
* </p>
|
|
|
|
|
*/
|
|
|
|
|
private void showLayoutSettingsDialog() {
|
|
|
|
|
LayoutSettingsDialog dialog = new LayoutSettingsDialog(this, mLayoutManagerController);
|
|
|
|
|
dialog.show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 显示Toast提示
|
|
|
|
|
* <p>
|
|
|
|
|
* 显示简短的提示信息,自动消失。
|
|
|
|
|
* </p>
|
|
|
|
|
* @param message 提示信息
|
|
|
|
|
*/
|
|
|
|
|
private void showToast(String message) {
|
|
|
|
|
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查是否处于同步模式
|
|
|
|
|
* <p>
|
|
|
|
|
@ -1202,22 +1260,21 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
* </ul>
|
|
|
|
|
* </p>
|
|
|
|
|
*/
|
|
|
|
|
private class OnListItemClickListener implements OnItemClickListener {
|
|
|
|
|
private class OnListItemClickListener implements NotesRecyclerViewAdapter.OnItemClickListener {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 列表项点击事件处理
|
|
|
|
|
*
|
|
|
|
|
* @param parent 父视图
|
|
|
|
|
* @param view 被点击的视图
|
|
|
|
|
* @param position 列表项位置
|
|
|
|
|
* @param id 列表项ID
|
|
|
|
|
*/
|
|
|
|
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
|
|
|
|
if (view instanceof NotesListItem) {
|
|
|
|
|
NoteItemData item = ((NotesListItem) view).getItemData();
|
|
|
|
|
public void onItemClick(View view, int position, long id) {
|
|
|
|
|
Cursor cursor = (Cursor) mNotesListAdapter.getItem(position);
|
|
|
|
|
if (cursor != null) {
|
|
|
|
|
NoteItemData item = new NoteItemData(NotesListActivity.this, cursor);
|
|
|
|
|
if (mNotesListAdapter.isInChoiceMode()) {
|
|
|
|
|
if (item.getType() == Notes.TYPE_NOTE) {
|
|
|
|
|
position = position - mNotesListView.getHeaderViewsCount();
|
|
|
|
|
mModeCallBack.onItemCheckedStateChanged(null, position, id,
|
|
|
|
|
!mNotesListAdapter.isSelectedItem(position));
|
|
|
|
|
}
|
|
|
|
|
@ -1279,24 +1336,25 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
/**
|
|
|
|
|
* 列表项长按事件处理
|
|
|
|
|
*
|
|
|
|
|
* @param parent 父视图
|
|
|
|
|
* @param view 被长按的视图
|
|
|
|
|
* @param position 列表项位置
|
|
|
|
|
* @param id 列表项ID
|
|
|
|
|
* @return true表示事件已处理
|
|
|
|
|
*/
|
|
|
|
|
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
|
|
|
|
if (view instanceof NotesListItem) {
|
|
|
|
|
mFocusNoteDataItem = ((NotesListItem) view).getItemData();
|
|
|
|
|
public boolean onItemLongClick(View view, int position, long id) {
|
|
|
|
|
Cursor cursor = (Cursor) mNotesListAdapter.getItem(position);
|
|
|
|
|
if (cursor != null) {
|
|
|
|
|
mFocusNoteDataItem = new NoteItemData(NotesListActivity.this, cursor);
|
|
|
|
|
if (mFocusNoteDataItem.getType() == Notes.TYPE_NOTE && !mNotesListAdapter.isInChoiceMode()) {
|
|
|
|
|
if (mNotesListView.startActionMode(mModeCallBack) != null) {
|
|
|
|
|
if (startActionMode(mModeCallBack) != null) {
|
|
|
|
|
mModeCallBack.onItemCheckedStateChanged(null, position, id, true);
|
|
|
|
|
mNotesListView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
|
|
|
|
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
|
|
|
|
} else {
|
|
|
|
|
Log.e(TAG, "startActionMode fails");
|
|
|
|
|
}
|
|
|
|
|
} else if (mFocusNoteDataItem.getType() == Notes.TYPE_FOLDER) {
|
|
|
|
|
mNotesListView.setOnCreateContextMenuListener(mFolderOnCreateContextMenuListener);
|
|
|
|
|
registerForContextMenu(view);
|
|
|
|
|
openContextMenu(view);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
|