├── .gitignore ├── .idea ├── gradle.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── example │ │ └── plainolnotes3 │ │ ├── DatabaseTest.java │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── plainolnotes3 │ │ │ ├── EditorActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── database │ │ │ ├── AppDatabase.java │ │ │ ├── AppRepository.java │ │ │ ├── DateConverter.java │ │ │ ├── NoteDao.java │ │ │ └── NoteEntity.java │ │ │ ├── ui │ │ │ └── NotesAdapter.java │ │ │ ├── utilities │ │ │ ├── Constants.java │ │ │ └── SampleData.java │ │ │ └── viewmodel │ │ │ ├── EditorViewModel.java │ │ │ └── MainViewModel.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_add.xml │ │ ├── ic_check.xml │ │ ├── ic_delete.xml │ │ ├── ic_edit.xml │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_editor.xml │ │ ├── activity_main.xml │ │ ├── content_editor.xml │ │ ├── content_main.xml │ │ └── note_list_item.xml │ │ ├── menu │ │ ├── menu_editor.xml │ │ └── menu_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── example │ └── plainolnotes3 │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── resources ├── code │ └── sample.java └── graphics │ └── logo_1024x1024.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/libraries 5 | /.idea/caches 6 | /.idea/codeStyles 7 | /.idea/modules.xml 8 | /.idea/workspace.xml 9 | .DS_Store 10 | /build 11 | /captures 12 | .externalNativeBuild 13 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PlainOlNotes3 2 | Plain Ol' Notes 3, a simple note-taking app for Android 3 | 4 | This repository contains exercise files for the course "Building an Android App with Architecture Components". 5 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | defaultConfig { 6 | applicationId "com.example.plainolnotes3" 7 | minSdkVersion 15 8 | targetSdkVersion 27 9 | versionCode 1 10 | versionName "1.0" 11 | vectorDrawables.useSupportLibrary = true 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(include: ['*.jar'], dir: 'libs') 24 | implementation 'com.android.support:appcompat-v7:27.1.0' 25 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 26 | implementation 'com.android.support:design:27.1.0' 27 | testImplementation 'junit:junit:4.12' 28 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 29 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 30 | implementation 'android.arch.lifecycle:extensions:1.1.1' 31 | implementation 'android.arch.persistence.room:runtime:1.0.0' 32 | annotationProcessor "android.arch.persistence.room:compiler:1.0.0" 33 | implementation 'com.jakewharton:butterknife:8.8.1' 34 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' 35 | } 36 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/example/plainolnotes3/DatabaseTest.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3; 2 | 3 | import android.arch.persistence.room.Room; 4 | import android.content.Context; 5 | import android.support.test.InstrumentationRegistry; 6 | import android.support.test.runner.AndroidJUnit4; 7 | import android.util.Log; 8 | 9 | import com.example.plainolnotes3.database.AppDatabase; 10 | import com.example.plainolnotes3.database.NoteDao; 11 | import com.example.plainolnotes3.database.NoteEntity; 12 | import com.example.plainolnotes3.utilities.SampleData; 13 | 14 | import org.junit.After; 15 | import org.junit.Before; 16 | import org.junit.Test; 17 | import org.junit.runner.RunWith; 18 | 19 | import static org.junit.Assert.*; 20 | 21 | @RunWith(AndroidJUnit4.class) 22 | public class DatabaseTest { 23 | public static final String TAG = "Junit"; 24 | private AppDatabase mDb; 25 | private NoteDao mDao; 26 | 27 | @Before 28 | public void createDb() { 29 | Context context = InstrumentationRegistry.getTargetContext(); 30 | mDb = Room.inMemoryDatabaseBuilder(context, 31 | AppDatabase.class).build(); 32 | mDao = mDb.noteDao(); 33 | Log.i(TAG, "createDb"); 34 | } 35 | 36 | @After 37 | public void closeDb() { 38 | mDb.close(); 39 | Log.i(TAG, "closeDb"); 40 | } 41 | 42 | @Test 43 | public void createAndRetrieveNotes() { 44 | mDao.insertAll(SampleData.getNotes()); 45 | int count = mDao.getCount(); 46 | Log.i(TAG, "createAndRetrieveNotes: count=" + count); 47 | assertEquals(SampleData.getNotes().size(), count); 48 | } 49 | 50 | @Test 51 | public void compareStrings() { 52 | mDao.insertAll(SampleData.getNotes()); 53 | NoteEntity original = SampleData.getNotes().get(0); 54 | NoteEntity fromDb = mDao.getNoteById(1); 55 | assertEquals(original.getText(), fromDb.getText()); 56 | assertEquals(1, fromDb.getId()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/example/plainolnotes3/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.example.plainolnotes3", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/com/example/plainolnotes3/EditorActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3; 2 | 3 | import android.arch.lifecycle.Observer; 4 | import android.arch.lifecycle.ViewModelProviders; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | import android.view.Menu; 10 | import android.view.MenuInflater; 11 | import android.view.MenuItem; 12 | import android.widget.TextView; 13 | 14 | import com.example.plainolnotes3.database.NoteEntity; 15 | import com.example.plainolnotes3.viewmodel.EditorViewModel; 16 | 17 | import butterknife.BindView; 18 | import butterknife.ButterKnife; 19 | 20 | import static com.example.plainolnotes3.utilities.Constants.EDITING_KEY; 21 | import static com.example.plainolnotes3.utilities.Constants.NOTE_ID_KEY; 22 | 23 | public class EditorActivity extends AppCompatActivity { 24 | 25 | @BindView(R.id.note_text) 26 | TextView mTextView; 27 | 28 | private EditorViewModel mViewModel; 29 | private boolean mNewNote, mEditing; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_editor); 35 | Toolbar toolbar = findViewById(R.id.toolbar); 36 | setSupportActionBar(toolbar); 37 | getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_check); 38 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 39 | 40 | ButterKnife.bind(this); 41 | 42 | if (savedInstanceState != null) { 43 | mEditing = savedInstanceState.getBoolean(EDITING_KEY); 44 | } 45 | 46 | initViewModel(); 47 | } 48 | 49 | private void initViewModel() { 50 | mViewModel = ViewModelProviders.of(this) 51 | .get(EditorViewModel.class); 52 | 53 | mViewModel.mLiveNote.observe(this, new Observer() { 54 | @Override 55 | public void onChanged(@Nullable NoteEntity noteEntity) { 56 | if (noteEntity != null && !mEditing) { 57 | mTextView.setText(noteEntity.getText()); 58 | } 59 | } 60 | }); 61 | 62 | Bundle extras = getIntent().getExtras(); 63 | if (extras == null) { 64 | setTitle(getString(R.string.new_note)); 65 | mNewNote = true; 66 | } else { 67 | setTitle(getString(R.string.edit_note)); 68 | int noteId = extras.getInt(NOTE_ID_KEY); 69 | mViewModel.loadData(noteId); 70 | } 71 | } 72 | 73 | @Override 74 | public boolean onCreateOptionsMenu(Menu menu) { 75 | if (!mNewNote) { 76 | MenuInflater inflater = getMenuInflater(); 77 | inflater.inflate(R.menu.menu_editor, menu); 78 | } 79 | return super.onCreateOptionsMenu(menu); 80 | } 81 | 82 | @Override 83 | public boolean onOptionsItemSelected(MenuItem item) { 84 | if (item.getItemId() == android.R.id.home) { 85 | saveAndReturn(); 86 | return true; 87 | } else if (item.getItemId() == R.id.action_delete) { 88 | mViewModel.deleteNote(); 89 | finish(); 90 | } 91 | return super.onOptionsItemSelected(item); 92 | } 93 | 94 | @Override 95 | public void onBackPressed() { 96 | saveAndReturn(); 97 | } 98 | 99 | private void saveAndReturn() { 100 | mViewModel.saveNote(mTextView.getText().toString()); 101 | finish(); 102 | } 103 | 104 | @Override 105 | protected void onSaveInstanceState(Bundle outState) { 106 | outState.putBoolean(EDITING_KEY, true); 107 | super.onSaveInstanceState(outState); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/plainolnotes3/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3; 2 | 3 | import android.arch.lifecycle.Observer; 4 | import android.arch.lifecycle.ViewModelProviders; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.support.annotation.Nullable; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.support.v7.widget.DividerItemDecoration; 10 | import android.support.v7.widget.LinearLayoutManager; 11 | import android.support.v7.widget.RecyclerView; 12 | import android.support.v7.widget.Toolbar; 13 | import android.view.Menu; 14 | import android.view.MenuItem; 15 | 16 | import com.example.plainolnotes3.database.NoteEntity; 17 | import com.example.plainolnotes3.ui.NotesAdapter; 18 | import com.example.plainolnotes3.viewmodel.MainViewModel; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | import butterknife.BindView; 24 | import butterknife.ButterKnife; 25 | import butterknife.OnClick; 26 | 27 | public class MainActivity extends AppCompatActivity { 28 | 29 | @BindView(R.id.recycler_view) 30 | RecyclerView mRecyclerView; 31 | 32 | @OnClick(R.id.fab) 33 | void fabClickHandler() { 34 | Intent intent = new Intent(this, EditorActivity.class); 35 | startActivity(intent); 36 | } 37 | 38 | private List notesData = new ArrayList<>(); 39 | private NotesAdapter mAdapter; 40 | private MainViewModel mViewModel; 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | 45 | super.onCreate(savedInstanceState); 46 | setContentView(R.layout.activity_main); 47 | Toolbar toolbar = findViewById(R.id.toolbar); 48 | setSupportActionBar(toolbar); 49 | 50 | ButterKnife.bind(this); 51 | initRecyclerView(); 52 | initViewModel(); 53 | 54 | } 55 | 56 | private void initViewModel() { 57 | 58 | final Observer> notesObserver = 59 | new Observer>() { 60 | @Override 61 | public void onChanged(@Nullable List noteEntities) { 62 | notesData.clear(); 63 | notesData.addAll(noteEntities); 64 | 65 | if (mAdapter == null) { 66 | mAdapter = new NotesAdapter(notesData, 67 | MainActivity.this); 68 | mRecyclerView.setAdapter(mAdapter); 69 | } else { 70 | mAdapter.notifyDataSetChanged(); 71 | } 72 | 73 | } 74 | }; 75 | 76 | mViewModel = ViewModelProviders.of(this) 77 | .get(MainViewModel.class); 78 | mViewModel.mNotes.observe(this, notesObserver); 79 | } 80 | 81 | private void initRecyclerView() { 82 | mRecyclerView.setHasFixedSize(true); 83 | LinearLayoutManager layoutManager = new LinearLayoutManager(this); 84 | mRecyclerView.setLayoutManager(layoutManager); 85 | 86 | DividerItemDecoration divider = new DividerItemDecoration( 87 | mRecyclerView.getContext(), layoutManager.getOrientation()); 88 | mRecyclerView.addItemDecoration(divider); 89 | 90 | } 91 | 92 | @Override 93 | public boolean onCreateOptionsMenu(Menu menu) { 94 | // Inflate the menu; this adds items to the action bar if it is present. 95 | getMenuInflater().inflate(R.menu.menu_main, menu); 96 | return true; 97 | } 98 | 99 | @Override 100 | public boolean onOptionsItemSelected(MenuItem item) { 101 | // Handle action bar item clicks here. The action bar will 102 | // automatically handle clicks on the Home/Up button, so long 103 | // as you specify a parent activity in AndroidManifest.xml. 104 | int id = item.getItemId(); 105 | 106 | //noinspection SimplifiableIfStatement 107 | if (id == R.id.action_add_sample_data) { 108 | addSampleData(); 109 | return true; 110 | } else if (id == R.id.action_delete_all) { 111 | deleteAllNotes(); 112 | return true; 113 | } 114 | 115 | return super.onOptionsItemSelected(item); 116 | } 117 | 118 | private void deleteAllNotes() { 119 | mViewModel.deleteAllNotes(); 120 | } 121 | 122 | private void addSampleData() { 123 | mViewModel.addSampleData(); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/plainolnotes3/database/AppDatabase.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3.database; 2 | 3 | import android.arch.persistence.room.Database; 4 | import android.arch.persistence.room.Room; 5 | import android.arch.persistence.room.RoomDatabase; 6 | import android.arch.persistence.room.TypeConverters; 7 | import android.content.Context; 8 | 9 | @Database(entities = {NoteEntity.class}, version = 1) 10 | @TypeConverters(DateConverter.class) 11 | public abstract class AppDatabase extends RoomDatabase { 12 | public static final String DATABASE_NAME = "AppDatabase.db"; 13 | private static volatile AppDatabase instance; 14 | private static final Object LOCK = new Object(); 15 | 16 | public abstract NoteDao noteDao(); 17 | 18 | public static AppDatabase getInstance(Context context) { 19 | if (instance == null) { 20 | synchronized (LOCK) { 21 | if (instance == null) { 22 | instance = Room.databaseBuilder(context.getApplicationContext(), 23 | AppDatabase.class, DATABASE_NAME).build(); 24 | } 25 | } 26 | } 27 | 28 | return instance; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/plainolnotes3/database/AppRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3.database; 2 | 3 | import android.arch.lifecycle.LiveData; 4 | import android.content.Context; 5 | 6 | import com.example.plainolnotes3.utilities.SampleData; 7 | 8 | import java.util.List; 9 | import java.util.concurrent.Executor; 10 | import java.util.concurrent.Executors; 11 | 12 | public class AppRepository { 13 | private static AppRepository ourInstance; 14 | 15 | public LiveData> mNotes; 16 | private AppDatabase mDb; 17 | private Executor executor = Executors.newSingleThreadExecutor(); 18 | 19 | public static AppRepository getInstance(Context context) { 20 | if (ourInstance == null) { 21 | ourInstance = new AppRepository(context); 22 | } 23 | return ourInstance; 24 | } 25 | 26 | private AppRepository(Context context) { 27 | mDb = AppDatabase.getInstance(context); 28 | mNotes = getAllNotes(); 29 | } 30 | 31 | public void addSampleData() { 32 | executor.execute(new Runnable() { 33 | @Override 34 | public void run() { 35 | mDb.noteDao().insertAll(SampleData.getNotes()); 36 | } 37 | }); 38 | } 39 | 40 | private LiveData> getAllNotes() { 41 | return mDb.noteDao().getAll(); 42 | } 43 | 44 | public void deleteAllNotes() { 45 | executor.execute(new Runnable() { 46 | @Override 47 | public void run() { 48 | mDb.noteDao().deleteAll(); 49 | } 50 | }); 51 | } 52 | 53 | public NoteEntity getNoteById(int noteId) { 54 | return mDb.noteDao().getNoteById(noteId); 55 | } 56 | 57 | public void insertNote(final NoteEntity note) { 58 | executor.execute(new Runnable() { 59 | @Override 60 | public void run() { 61 | mDb.noteDao().insertNote(note); 62 | } 63 | }); 64 | } 65 | 66 | public void deleteNote(final NoteEntity note) { 67 | executor.execute(new Runnable() { 68 | @Override 69 | public void run() { 70 | mDb.noteDao().deleteNote(note); 71 | } 72 | }); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/plainolnotes3/database/DateConverter.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3.database; 2 | 3 | import android.arch.persistence.room.TypeConverter; 4 | 5 | import java.util.Date; 6 | 7 | public class DateConverter { 8 | 9 | @TypeConverter 10 | public static Date toDate(Long timestamp) { 11 | return timestamp == null ? null : new Date(timestamp); 12 | } 13 | 14 | @TypeConverter 15 | public static Long toTimestamp(Date date) { 16 | return date == null ? null : date.getTime(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/plainolnotes3/database/NoteDao.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3.database; 2 | 3 | import android.arch.lifecycle.LiveData; 4 | import android.arch.persistence.room.Dao; 5 | import android.arch.persistence.room.Delete; 6 | import android.arch.persistence.room.Insert; 7 | import android.arch.persistence.room.OnConflictStrategy; 8 | import android.arch.persistence.room.Query; 9 | 10 | import java.util.List; 11 | 12 | @Dao 13 | public interface NoteDao { 14 | 15 | @Insert(onConflict = OnConflictStrategy.REPLACE) 16 | void insertNote(NoteEntity noteEntity); 17 | 18 | @Insert(onConflict = OnConflictStrategy.REPLACE) 19 | void insertAll(List notes); 20 | 21 | @Delete 22 | void deleteNote(NoteEntity noteEntity); 23 | 24 | @Query("SELECT * FROM notes WHERE id = :id") 25 | NoteEntity getNoteById(int id); 26 | 27 | @Query("SELECT * FROM notes ORDER BY date DESC") 28 | LiveData> getAll(); 29 | 30 | @Query("DELETE FROM notes") 31 | int deleteAll(); 32 | 33 | @Query("SELECT COUNT(*) FROM notes") 34 | int getCount(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/plainolnotes3/database/NoteEntity.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3.database; 2 | 3 | import android.arch.persistence.room.Entity; 4 | import android.arch.persistence.room.Ignore; 5 | import android.arch.persistence.room.PrimaryKey; 6 | 7 | import java.util.Date; 8 | 9 | @Entity(tableName = "notes") 10 | public class NoteEntity { 11 | @PrimaryKey(autoGenerate = true) 12 | private int id; 13 | private Date date; 14 | private String text; 15 | 16 | @Ignore 17 | public NoteEntity() { 18 | } 19 | 20 | public NoteEntity(int id, Date date, String text) { 21 | this.id = id; 22 | this.date = date; 23 | this.text = text; 24 | } 25 | 26 | @Ignore 27 | public NoteEntity(Date date, String text) { 28 | this.date = date; 29 | this.text = text; 30 | } 31 | 32 | public int getId() { 33 | return id; 34 | } 35 | 36 | public void setId(int id) { 37 | this.id = id; 38 | } 39 | 40 | public Date getDate() { 41 | return date; 42 | } 43 | 44 | public void setDate(Date date) { 45 | this.date = date; 46 | } 47 | 48 | public String getText() { 49 | return text; 50 | } 51 | 52 | public void setText(String text) { 53 | this.text = text; 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | return "NoteEntity{" + 59 | "id=" + id + 60 | ", date=" + date + 61 | ", text='" + text + '\'' + 62 | '}'; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/plainolnotes3/ui/NotesAdapter.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3.ui; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.support.annotation.NonNull; 6 | import android.support.design.widget.FloatingActionButton; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.TextView; 12 | 13 | import com.example.plainolnotes3.EditorActivity; 14 | import com.example.plainolnotes3.R; 15 | import com.example.plainolnotes3.database.NoteEntity; 16 | 17 | import java.util.List; 18 | 19 | import butterknife.BindView; 20 | import butterknife.ButterKnife; 21 | 22 | import static com.example.plainolnotes3.utilities.Constants.NOTE_ID_KEY; 23 | 24 | public class NotesAdapter extends RecyclerView.Adapter { 25 | 26 | private final List mNotes; 27 | private final Context mContext; 28 | 29 | public NotesAdapter(List mNotes, Context mContext) { 30 | this.mNotes = mNotes; 31 | this.mContext = mContext; 32 | } 33 | 34 | @NonNull 35 | @Override 36 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 37 | LayoutInflater inflater = LayoutInflater.from(parent.getContext()); 38 | View view = inflater.inflate(R.layout.note_list_item, parent, false); 39 | return new ViewHolder(view); 40 | } 41 | 42 | @Override 43 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 44 | final NoteEntity note = mNotes.get(position); 45 | holder.mTextView.setText(note.getText()); 46 | 47 | holder.mFab.setOnClickListener(new View.OnClickListener() { 48 | @Override 49 | public void onClick(View v) { 50 | Intent intent = new Intent(mContext, EditorActivity.class); 51 | intent.putExtra(NOTE_ID_KEY, note.getId()); 52 | mContext.startActivity(intent); 53 | } 54 | }); 55 | } 56 | 57 | @Override 58 | public int getItemCount() { 59 | return mNotes.size(); 60 | } 61 | 62 | public class ViewHolder extends RecyclerView.ViewHolder { 63 | @BindView(R.id.note_text) 64 | TextView mTextView; 65 | @BindView(R.id.fab) 66 | FloatingActionButton mFab; 67 | 68 | public ViewHolder(View itemView) { 69 | super(itemView); 70 | ButterKnife.bind(this, itemView); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/plainolnotes3/utilities/Constants.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3.utilities; 2 | 3 | public class Constants { 4 | public static final String NOTE_ID_KEY = "note_id_key"; 5 | public static final String EDITING_KEY = "editing_key"; 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/plainolnotes3/utilities/SampleData.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3.utilities; 2 | 3 | import com.example.plainolnotes3.database.NoteEntity; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Calendar; 7 | import java.util.Date; 8 | import java.util.GregorianCalendar; 9 | import java.util.List; 10 | 11 | public class SampleData { 12 | 13 | private static final String SAMPLE_TEXT_1 = "A simple note"; 14 | private static final String SAMPLE_TEXT_2 = "A note with a\nline feed"; 15 | private static final String SAMPLE_TEXT_3 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n" + 16 | "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"; 17 | 18 | private static Date getDate(int diff) { 19 | GregorianCalendar cal = new GregorianCalendar(); 20 | cal.add(Calendar.MILLISECOND, diff); 21 | return cal.getTime(); 22 | } 23 | 24 | public static List getNotes() { 25 | List notes = new ArrayList<>(); 26 | notes.add(new NoteEntity(getDate(0), SAMPLE_TEXT_1)); 27 | notes.add(new NoteEntity(getDate(-1), SAMPLE_TEXT_2)); 28 | notes.add(new NoteEntity(getDate(-2), SAMPLE_TEXT_3)); 29 | return notes; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/plainolnotes3/viewmodel/EditorViewModel.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3.viewmodel; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.AndroidViewModel; 5 | import android.arch.lifecycle.MutableLiveData; 6 | import android.support.annotation.NonNull; 7 | import android.text.TextUtils; 8 | 9 | import com.example.plainolnotes3.database.AppRepository; 10 | import com.example.plainolnotes3.database.NoteEntity; 11 | 12 | import java.util.Date; 13 | import java.util.concurrent.Executor; 14 | import java.util.concurrent.Executors; 15 | 16 | public class EditorViewModel extends AndroidViewModel { 17 | 18 | public MutableLiveData mLiveNote = 19 | new MutableLiveData<>(); 20 | private AppRepository mRepository; 21 | private Executor executor = Executors.newSingleThreadExecutor(); 22 | 23 | public EditorViewModel(@NonNull Application application) { 24 | super(application); 25 | mRepository = AppRepository.getInstance(getApplication()); 26 | } 27 | 28 | public void loadData(final int noteId) { 29 | executor.execute(new Runnable() { 30 | @Override 31 | public void run() { 32 | NoteEntity note = mRepository.getNoteById(noteId); 33 | mLiveNote.postValue(note); 34 | } 35 | }); 36 | } 37 | 38 | public void saveNote(String noteText) { 39 | NoteEntity note = mLiveNote.getValue(); 40 | 41 | if (note == null) { 42 | if (TextUtils.isEmpty(noteText.trim())) { 43 | return; 44 | } 45 | note = new NoteEntity(new Date(), noteText.trim()); 46 | } else { 47 | note.setText(noteText.trim()); 48 | } 49 | mRepository.insertNote(note); 50 | } 51 | 52 | public void deleteNote() { 53 | mRepository.deleteNote(mLiveNote.getValue()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/plainolnotes3/viewmodel/MainViewModel.java: -------------------------------------------------------------------------------- 1 | package com.example.plainolnotes3.viewmodel; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.AndroidViewModel; 5 | import android.arch.lifecycle.LiveData; 6 | import android.support.annotation.NonNull; 7 | 8 | import com.example.plainolnotes3.database.AppRepository; 9 | import com.example.plainolnotes3.database.NoteEntity; 10 | 11 | import java.util.List; 12 | 13 | public class MainViewModel extends AndroidViewModel { 14 | 15 | public LiveData> mNotes; 16 | private AppRepository mRepository; 17 | 18 | public MainViewModel(@NonNull Application application) { 19 | super(application); 20 | 21 | mRepository = AppRepository.getInstance(application.getApplicationContext()); 22 | mNotes = mRepository.mNotes; 23 | } 24 | 25 | public void addSampleData() { 26 | mRepository.addSampleData(); 27 | } 28 | 29 | public void deleteAllNotes() { 30 | mRepository.deleteAllNotes(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_check.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_edit.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_editor.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 25 | 26 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_editor.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/note_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 25 | 26 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_editor.xml: -------------------------------------------------------------------------------- 1 | 5 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidgassner/PlainOlNotes3/3a0dc9269e8f02f45f29a0f52586f21abb87c218/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | #333 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 18sp 4 | 8dp 5 | 180dp 6 | 16dp 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #00FFFF 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Plain Ol\' Notes 3 3 | Add sample data 4 | EditorActivity 5 | 6 | "Material is the metaphor.\n\n" 7 | 8 | "A material metaphor is the unifying theory of a rationalized space and a system of motion." 9 | "The material is grounded in tactile reality, inspired by the study of paper and ink, yet " 10 | "technologically advanced and open to imagination and magic.\n" 11 | "Surfaces and edges of the material provide visual cues that are grounded in reality. The " 12 | "use of familiar tactile attributes helps users quickly understand affordances. Yet the " 13 | "flexibility of the material creates new affordances that supercede those in the physical " 14 | "world, without breaking the rules of physics.\n" 15 | "The fundamentals of light, surface, and movement are key to conveying how objects move, " 16 | "interact, and exist in space and in relation to each other. Realistic lighting shows " 17 | "seams, divides space, and indicates moving parts.\n\n" 18 | 19 | "Bold, graphic, intentional.\n\n" 20 | 21 | "The foundational elements of print based design typography, grids, space, scale, color, " 22 | "and use of imagery guide visual treatments. These elements do far more than please the " 23 | "eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge " 24 | "imagery, large scale typography, and intentional white space create a bold and graphic " 25 | "interface that immerse the user in the experience.\n" 26 | "An emphasis on user actions makes core functionality immediately apparent and provides " 27 | "waypoints for the user.\n\n" 28 | 29 | "Motion provides meaning.\n\n" 30 | 31 | "Motion respects and reinforces the user as the prime mover. Primary user actions are " 32 | "inflection points that initiate motion, transforming the whole design.\n" 33 | "All action takes place in a single environment. Objects are presented to the user without " 34 | "breaking the continuity of experience even as they transform and reorganize.\n" 35 | "Motion is meaningful and appropriate, serving to focus attention and maintain continuity. " 36 | "Feedback is subtle yet clear. Transitions are efficient yet coherent.\n\n" 37 | 38 | "3D world.\n\n" 39 | 40 | "The material environment is a 3D space, which means all objects have x, y, and z " 41 | "dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the " 42 | "positive z-axis extending towards the viewer. Every sheet of material occupies a single " 43 | "position along the z-axis and has a standard 1dp thickness.\n" 44 | "On the web, the z-axis is used for layering and not for perspective. The 3D world is " 45 | "emulated by manipulating the y-axis.\n\n" 46 | 47 | "Light and shadow.\n\n" 48 | 49 | "Within the material environment, virtual lights illuminate the scene. Key lights create " 50 | "directional shadows, while ambient light creates soft shadows from all angles.\n" 51 | "Shadows in the material environment are cast by these two light sources. In Android " 52 | "development, shadows occur when light sources are blocked by sheets of material at " 53 | "various positions along the z-axis. On the web, shadows are depicted by manipulating the " 54 | "y-axis only. The following example shows the card with a height of 6dp.\n\n" 55 | 56 | "Resting elevation.\n\n" 57 | 58 | "All material objects, regardless of size, have a resting elevation, or default elevation " 59 | "that does not change. If an object changes elevation, it should return to its resting " 60 | "elevation as soon as possible.\n\n" 61 | 62 | "Component elevations.\n\n" 63 | 64 | "The resting elevation for a component type is consistent across apps (e.g., FAB elevation " 65 | "does not vary from 6dp in one app to 16dp in another app).\n" 66 | "Components may have different resting elevations across platforms, depending on the depth " 67 | "of the environment (e.g., TV has a greater depth than mobile or desktop).\n\n" 68 | 69 | "Responsive elevation and dynamic elevation offsets.\n\n" 70 | 71 | "Some component types have responsive elevation, meaning they change elevation in response " 72 | "to user input (e.g., normal, focused, and pressed) or system events. These elevation " 73 | "changes are consistently implemented using dynamic elevation offsets.\n" 74 | "Dynamic elevation offsets are the goal elevation that a component moves towards, relative " 75 | "to the component’s resting state. They ensure that elevation changes are consistent " 76 | "across actions and component types. For example, all components that lift on press have " 77 | "the same elevation change relative to their resting elevation.\n" 78 | "Once the input event is completed or cancelled, the component will return to its resting " 79 | "elevation.\n\n" 80 | 81 | "Avoiding elevation interference.\n\n" 82 | 83 | "Components with responsive elevations may encounter other components as they move between " 84 | "their resting elevations and dynamic elevation offsets. Because material cannot pass " 85 | "through other material, components avoid interfering with one another any number of ways, " 86 | "whether on a per component basis or using the entire app layout.\n" 87 | "On a component level, components can move or be removed before they cause interference. " 88 | "For example, a floating action button (FAB) can disappear or move off screen before a " 89 | "user picks up a card, or it can move if a snackbar appears.\n" 90 | "On the layout level, design your app layout to minimize opportunities for interference. " 91 | "For example, position the FAB to one side of stream of a cards so the FAB won’t interfere " 92 | "when a user tries to pick up one of cards.\n\n" 93 | 94 | Enter note 95 | Delete all notes 96 | New note 97 | Edit note 98 | Delete 99 | 100 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |