Просмотр и редактирование заметок.

Урок 25 — Просмотр и редактирование заметок.

Что ж, мы научили приложение создавать заметки, но было бы неплохо, чтобы их ещё можно было просматривать.

Просмотр заметки

Создайте новую Activity по аналогии с CreateNoteActivity: NoteActivity.

Разметка будет такой:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.skillberg.notes.NoteActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <include layout="@layout/toolbar" />

    </android.support.design.widget.AppBarLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:orientation="vertical">

            <TextView
                android:id="@+id/text_tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fontFamily="sans-serif"
                android:textColor="@color/colorTextPrimary"
                android:textSize="16sp" />

        </LinearLayout>


    </ScrollView>

</android.support.design.widget.CoordinatorLayout>

А Java-код таким:

public class NoteActivity extends AppCompatActivity {

    private TextView noteTv;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_note);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        noteTv = findViewById(R.id.text_tv);
    }

}

Для того, чтобы Activity могла отобразить заметку, нужно передать в неё id заметки, после чего мы загрузим заметку из БД, используя этот id.

Мы можем передать id через Intent при вызове Activity, используя механизм Extras. Поскольку хорошим тоном является объявление ключей Extra в качестве констант, создадим такую константу:

public static final String EXTRA_NOTE_ID = "note_id";

Ещё нам понадобится поле, в котором мы будем хранить идентификатор заметки:

private long noteId;

Далее в конце onCreate() получим идентификатор заметки:

noteId = getIntent().getLongExtra(EXTRA_NOTE_ID, -1);
if (noteId == -1) {
    finish();
}

Если идентификатор заметки равен -1, значит идентификатор не был передан. В таком случае мы просто завершаем Activity.

Теперь, точно так же, как и в MainActivity, будем использовать CursorLoader. Сделайте это сами.

Метод onCreateLoader() будет выглядеть несколько иначе:

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CursorLoader(
            this,  // Контекст
            ContentUris.withAppendedId(NotesContract.Notes.URI, noteId), // URI
            NotesContract.Notes.SINGLE_PROJECTION, // Столбцы
            null, // Параметры выборки
            null, // Аргументы выборки
            null // Сортировка по умолчанию
    );
}

Изменились два параметра:

  1. uri — теперь мы передаём туда URI конкретной заметки.
  2. projection — мы изменили проекцию, поскольку при выборке конкретной заметки нам нужны все столбцы, а не ограниченный набор, как при выборке списка.

Всё остальное ContentResolver сделает за нас!

Обработка кликов по заметке

Мы с вами уже делали обработку кликов в адаптере. Давайте вы сделаете её сами, а я вам лишь подскажу, что именно нам нужно, и покажу интерфейс Listener-а:

public interface OnNoteClickListener {
    void onNoteClick(long noteId);
}

Поскольку нам понадобится идентификатор заметки, нужно будет получить его из курсора. Сделайте это в методе onBindViewHolder по аналогии с другими столбцами, но не забудьте, что идентификатор — это не строка, а long.

После этого установите его в качестве тега во ViewHolder.

Не стесняйтесь подглядеть в тот код, что мы писали ранее, если не помните, как это делается.

Теперь нужно реализовать Listener в MainActivity и вызвать в нём NoteActivity:

private final NotesAdapter.OnNoteClickListener onNoteClickListener = new NotesAdapter.OnNoteClickListener() {
    @Override
    public void onNoteClick(long noteId) {
        Intent intent = new Intent(MainActivity.this, NoteActivity.class);
        intent.putExtra(NoteActivity.EXTRA_NOTE_ID, noteId);

        startActivity(intent);
    }
};

В принципе, это ничем не отличается от обычного вызова Activity с использованием Intent, кроме того, что мы передаём идентификатор заметки в Extras.

На данный момент метод onLoadFinished() в NoteActivity должен выглядеть так:

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    Log.i("Test", "Load finished: " + cursor.getCount());

    cursor.setNotificationUri(getContentResolver(), NotesContract.Notes.URI);
}

Если вы сейчас запустите приложение и кликните на заметку, то увидите в логах примерно следующее:

11-02 03:44:42.656 7284-7284/com.skillberg.notes I/Test: Load finished: 1

Это значит, что заметка загрузилась (учтите, что цифра должна равняться именно единице).

Теперь отобразим информацию о заметке — для этого получим данные из курсора точно так же, как и ранее в адаптере.

Создадим метод, который будет это делать:

private void displayNote(Cursor cursor) {
    if (!cursor.moveToFirst()) {
        // Если не получилось перейти к первой строке — завершаем Activity
        finish();
    }

    String title = cursor.getString(cursor.getColumnIndexOrThrow(NotesContract.Notes.COLUMN_TITLE));
    String noteText = cursor.getString(cursor.getColumnIndexOrThrow(NotesContract.Notes.COLUMN_NOTE));

    setTitle(title);
    noteTv.setText(noteText);
}

И вызовем метод в конце onLoadFinished():

displayNote(cursor);

Откройте заметку, и вы увидите, что она отображается:

Отображение заметки
Отображение заметки

Кнопка "назад" в Toolbar

Хорошим тоном является отображение кнопки назад (в виде стрелки) в Toolbar, чтобы пользователь мог вернуться на предыдущий экран не только физической кнопкой "назад".

Делается это достаточно просто.

Во-первых, в методе onCreate() сразу после установки тулбара добавьте такую строчку:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

Этой строчкой мы включили отображение кнопки. Осталось лишь обработать нажатие на эту кнопку и завершить Activity.

Эта кнопка, по сути, является элементом меню, поэтому обработать клик на неё мы можем в методе onOptionsItemSelected():

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            finish();
            return true;

        default:
            return super.onOptionsItemSelected(item);
    }
}

android.R.id.home — идентификатор кнопки назад. По клику на неё мы просто завершаем Activity.

Запустите приложение и попробуйте:

Кнопка "назад" в Toolbar
Кнопка "назад" в Toolbar

Редактирование заметки

Для редактирования заметки мы будем использовать тот же экран, что и для создания.

Алгоритм таков: если в CreateNoteActivity был передан идентификатор заметки, то загружаем заметку по ID, отображаем её в полях редактирования. При сохранении обновляем заметку.

Если же идентификатор передан не был, то действуем как и ранее — создаём новую заметку.

Конечно же, пользователю нужно на что-то нажать, чтобы перейти к редактированию. Пусть это будет кнопка редактирования в Toolbar (такая же, как и кнопка сохранения на экране создания заметки).

Создайте кнопку самостоятельно по примеру из предыдущего урока.

Создайте метод editNote(), который будет вызван из обработчика клика на элемент меню:

private void editNote() {
    Intent intent = new Intent(this, CreateNoteActivity.class);
    intent.putExtra(CreateNoteActivity.EXTRA_NOTE_ID, noteId);

    startActivity(intent);
}

Реализуйте получение заметки в CreateNoteActivity точно так же, как и в NoteActivity (с одним отличием — если Extra с идентификатором заметки не была передана, то мы не завершаем Activity):


Продолжение доступно на платных тарифах

Это недорого — всего от 440 ₽ в месяц!


ВЫБРАТЬ ТАРИФ


Продолжение доступно после регистрации

Все уроки на сайте доступны абсолютно бесплатно после регистрации.

Регистрация займёт меньше минуты ;)