├── .gitignore ├── .idea ├── caches │ └── build_file_checksums.ser ├── codeStyles │ └── Project.xml ├── gradle.xml ├── markdown-navigator.xml ├── markdown-navigator │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── info │ │ └── androidhive │ │ └── sqlite │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── info │ │ │ └── androidhive │ │ │ └── sqlite │ │ │ ├── database │ │ │ ├── DatabaseHelper.java │ │ │ └── model │ │ │ │ └── Note.java │ │ │ ├── utils │ │ │ ├── MyDividerItemDecoration.java │ │ │ └── RecyclerTouchListener.java │ │ │ └── view │ │ │ ├── MainActivity.java │ │ │ └── NotesAdapter.java │ └── res │ │ ├── drawable-hdpi │ │ └── ic_add_white_24dp.png │ │ ├── drawable-mdpi │ │ └── ic_add_white_24dp.png │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xhdpi │ │ └── ic_add_white_24dp.png │ │ ├── drawable-xxhdpi │ │ └── ic_add_white_24dp.png │ │ ├── drawable-xxxhdpi │ │ └── ic_add_white_24dp.png │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── content_main.xml │ │ ├── note_dialog.xml │ │ └── note_list_row.xml │ │ ├── menu │ │ └── 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 │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── info │ └── androidhive │ └── sqlite │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 36 | 37 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Android **Notes App** demonstrating **SQLite** database. 2 | 3 | [Tutorial](https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/) 4 | 5 | [Apk](http://download.androidhive.info/apk/sqlite-notes-app.apk) 6 | 7 | [Video Demo](https://www.youtube.com/watch?v=4YxUtIkG_gc) 8 | 9 | ![Android SQLite Notes App](https://www.androidhive.info/wp-content/uploads/2011/11/android-sqlite-notes-app.png) -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | defaultConfig { 6 | applicationId "info.androidhive.sqlite" 7 | minSdkVersion 16 8 | targetSdkVersion 27 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | implementation 'com.android.support:appcompat-v7:27.1.1' 24 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 25 | implementation 'com.android.support:design:27.1.1' 26 | testImplementation 'junit:junit:4.12' 27 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 28 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 29 | } -------------------------------------------------------------------------------- /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/info/androidhive/sqlite/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.sqlite; 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() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("info.androidhive.sqlite", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/sqlite/database/DatabaseHelper.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.sqlite.database; 2 | 3 | import android.content.ContentValues; 4 | import android.content.Context; 5 | import android.database.Cursor; 6 | import android.database.sqlite.SQLiteDatabase; 7 | import android.database.sqlite.SQLiteOpenHelper; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import info.androidhive.sqlite.database.model.Note; 13 | 14 | /** 15 | * Created by ravi on 15/03/18. 16 | */ 17 | 18 | public class DatabaseHelper extends SQLiteOpenHelper { 19 | 20 | // Database Version 21 | private static final int DATABASE_VERSION = 1; 22 | 23 | // Database Name 24 | private static final String DATABASE_NAME = "notes_db"; 25 | 26 | 27 | public DatabaseHelper(Context context) { 28 | super(context, DATABASE_NAME, null, DATABASE_VERSION); 29 | } 30 | 31 | // Creating Tables 32 | @Override 33 | public void onCreate(SQLiteDatabase db) { 34 | 35 | // create notes table 36 | db.execSQL(Note.CREATE_TABLE); 37 | } 38 | 39 | // Upgrading database 40 | @Override 41 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 42 | // Drop older table if existed 43 | db.execSQL("DROP TABLE IF EXISTS " + Note.TABLE_NAME); 44 | 45 | // Create tables again 46 | onCreate(db); 47 | } 48 | 49 | public long insertNote(String note) { 50 | // get writable database as we want to write data 51 | SQLiteDatabase db = this.getWritableDatabase(); 52 | 53 | ContentValues values = new ContentValues(); 54 | // `id` and `timestamp` will be inserted automatically. 55 | // no need to add them 56 | values.put(Note.COLUMN_NOTE, note); 57 | 58 | // insert row 59 | long id = db.insert(Note.TABLE_NAME, null, values); 60 | 61 | // close db connection 62 | db.close(); 63 | 64 | // return newly inserted row id 65 | return id; 66 | } 67 | 68 | public Note getNote(long id) { 69 | // get readable database as we are not inserting anything 70 | SQLiteDatabase db = this.getReadableDatabase(); 71 | 72 | Cursor cursor = db.query(Note.TABLE_NAME, 73 | new String[]{Note.COLUMN_ID, Note.COLUMN_NOTE, Note.COLUMN_TIMESTAMP}, 74 | Note.COLUMN_ID + "=?", 75 | new String[]{String.valueOf(id)}, null, null, null, null); 76 | 77 | if (cursor != null) 78 | cursor.moveToFirst(); 79 | 80 | // prepare note object 81 | Note note = new Note( 82 | cursor.getInt(cursor.getColumnIndex(Note.COLUMN_ID)), 83 | cursor.getString(cursor.getColumnIndex(Note.COLUMN_NOTE)), 84 | cursor.getString(cursor.getColumnIndex(Note.COLUMN_TIMESTAMP))); 85 | 86 | // close the db connection 87 | cursor.close(); 88 | 89 | return note; 90 | } 91 | 92 | public List getAllNotes() { 93 | List notes = new ArrayList<>(); 94 | 95 | // Select All Query 96 | String selectQuery = "SELECT * FROM " + Note.TABLE_NAME + " ORDER BY " + 97 | Note.COLUMN_TIMESTAMP + " DESC"; 98 | 99 | SQLiteDatabase db = this.getWritableDatabase(); 100 | Cursor cursor = db.rawQuery(selectQuery, null); 101 | 102 | // looping through all rows and adding to list 103 | if (cursor.moveToFirst()) { 104 | do { 105 | Note note = new Note(); 106 | note.setId(cursor.getInt(cursor.getColumnIndex(Note.COLUMN_ID))); 107 | note.setNote(cursor.getString(cursor.getColumnIndex(Note.COLUMN_NOTE))); 108 | note.setTimestamp(cursor.getString(cursor.getColumnIndex(Note.COLUMN_TIMESTAMP))); 109 | 110 | notes.add(note); 111 | } while (cursor.moveToNext()); 112 | } 113 | 114 | // close db connection 115 | db.close(); 116 | 117 | // return notes list 118 | return notes; 119 | } 120 | 121 | public int getNotesCount() { 122 | String countQuery = "SELECT * FROM " + Note.TABLE_NAME; 123 | SQLiteDatabase db = this.getReadableDatabase(); 124 | Cursor cursor = db.rawQuery(countQuery, null); 125 | 126 | int count = cursor.getCount(); 127 | cursor.close(); 128 | 129 | 130 | // return count 131 | return count; 132 | } 133 | 134 | public int updateNote(Note note) { 135 | SQLiteDatabase db = this.getWritableDatabase(); 136 | 137 | ContentValues values = new ContentValues(); 138 | values.put(Note.COLUMN_NOTE, note.getNote()); 139 | 140 | // updating row 141 | return db.update(Note.TABLE_NAME, values, Note.COLUMN_ID + " = ?", 142 | new String[]{String.valueOf(note.getId())}); 143 | } 144 | 145 | public void deleteNote(Note note) { 146 | SQLiteDatabase db = this.getWritableDatabase(); 147 | db.delete(Note.TABLE_NAME, Note.COLUMN_ID + " = ?", 148 | new String[]{String.valueOf(note.getId())}); 149 | db.close(); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/sqlite/database/model/Note.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.sqlite.database.model; 2 | 3 | /** 4 | * Created by ravi on 20/02/18. 5 | */ 6 | 7 | public class Note { 8 | public static final String TABLE_NAME = "notes"; 9 | 10 | public static final String COLUMN_ID = "id"; 11 | public static final String COLUMN_NOTE = "note"; 12 | public static final String COLUMN_TIMESTAMP = "timestamp"; 13 | 14 | private int id; 15 | private String note; 16 | private String timestamp; 17 | 18 | 19 | // Create table SQL query 20 | public static final String CREATE_TABLE = 21 | "CREATE TABLE " + TABLE_NAME + "(" 22 | + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," 23 | + COLUMN_NOTE + " TEXT," 24 | + COLUMN_TIMESTAMP + " DATETIME DEFAULT CURRENT_TIMESTAMP" 25 | + ")"; 26 | 27 | public Note() { 28 | } 29 | 30 | public Note(int id, String note, String timestamp) { 31 | this.id = id; 32 | this.note = note; 33 | this.timestamp = timestamp; 34 | } 35 | 36 | public int getId() { 37 | return id; 38 | } 39 | 40 | public String getNote() { 41 | return note; 42 | } 43 | 44 | public void setNote(String note) { 45 | this.note = note; 46 | } 47 | 48 | public String getTimestamp() { 49 | return timestamp; 50 | } 51 | 52 | public void setId(int id) { 53 | this.id = id; 54 | } 55 | 56 | public void setTimestamp(String timestamp) { 57 | this.timestamp = timestamp; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/sqlite/utils/MyDividerItemDecoration.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.sqlite.utils; 2 | 3 | /** 4 | * Created by ravi on 18/01/18. 5 | */ 6 | 7 | import android.content.Context; 8 | import android.content.res.Resources; 9 | import android.content.res.TypedArray; 10 | import android.graphics.Canvas; 11 | import android.graphics.Rect; 12 | import android.graphics.drawable.Drawable; 13 | import android.support.v7.widget.LinearLayoutManager; 14 | import android.support.v7.widget.RecyclerView; 15 | import android.util.TypedValue; 16 | import android.view.View; 17 | 18 | 19 | public class MyDividerItemDecoration extends RecyclerView.ItemDecoration { 20 | 21 | private static final int[] ATTRS = new int[]{ 22 | android.R.attr.listDivider 23 | }; 24 | 25 | public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; 26 | public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; 27 | 28 | private Drawable mDivider; 29 | private int mOrientation; 30 | private Context context; 31 | private int margin; 32 | 33 | public MyDividerItemDecoration(Context context, int orientation, int margin) { 34 | this.context = context; 35 | this.margin = margin; 36 | final TypedArray a = context.obtainStyledAttributes(ATTRS); 37 | mDivider = a.getDrawable(0); 38 | a.recycle(); 39 | setOrientation(orientation); 40 | } 41 | 42 | public void setOrientation(int orientation) { 43 | if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { 44 | throw new IllegalArgumentException("invalid orientation"); 45 | } 46 | mOrientation = orientation; 47 | } 48 | 49 | @Override 50 | public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { 51 | if (mOrientation == VERTICAL_LIST) { 52 | drawVertical(c, parent); 53 | } else { 54 | drawHorizontal(c, parent); 55 | } 56 | } 57 | 58 | public void drawVertical(Canvas c, RecyclerView parent) { 59 | final int left = parent.getPaddingLeft(); 60 | final int right = parent.getWidth() - parent.getPaddingRight(); 61 | 62 | final int childCount = parent.getChildCount(); 63 | for (int i = 0; i < childCount; i++) { 64 | final View child = parent.getChildAt(i); 65 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 66 | .getLayoutParams(); 67 | final int top = child.getBottom() + params.bottomMargin; 68 | final int bottom = top + mDivider.getIntrinsicHeight(); 69 | mDivider.setBounds(left + dpToPx(margin), top, right - dpToPx(margin), bottom); 70 | mDivider.draw(c); 71 | } 72 | } 73 | 74 | public void drawHorizontal(Canvas c, RecyclerView parent) { 75 | final int top = parent.getPaddingTop(); 76 | final int bottom = parent.getHeight() - parent.getPaddingBottom(); 77 | 78 | final int childCount = parent.getChildCount(); 79 | for (int i = 0; i < childCount; i++) { 80 | final View child = parent.getChildAt(i); 81 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 82 | .getLayoutParams(); 83 | final int left = child.getRight() + params.rightMargin; 84 | final int right = left + mDivider.getIntrinsicHeight(); 85 | mDivider.setBounds(left, top + dpToPx(margin), right, bottom - dpToPx(margin)); 86 | mDivider.draw(c); 87 | } 88 | } 89 | 90 | @Override 91 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 92 | if (mOrientation == VERTICAL_LIST) { 93 | outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); 94 | } else { 95 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); 96 | } 97 | } 98 | 99 | private int dpToPx(int dp) { 100 | Resources r = context.getResources(); 101 | return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics())); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/sqlite/utils/RecyclerTouchListener.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.sqlite.utils; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.GestureDetector; 6 | import android.view.MotionEvent; 7 | import android.view.View; 8 | 9 | /** 10 | * Created by ravi on 21/02/18. 11 | */ 12 | 13 | public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener { 14 | 15 | private ClickListener clicklistener; 16 | private GestureDetector gestureDetector; 17 | 18 | public RecyclerTouchListener(Context context, final RecyclerView recycleView, final ClickListener clicklistener) { 19 | 20 | this.clicklistener = clicklistener; 21 | gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { 22 | @Override 23 | public boolean onSingleTapUp(MotionEvent e) { 24 | return true; 25 | } 26 | 27 | @Override 28 | public void onLongPress(MotionEvent e) { 29 | View child = recycleView.findChildViewUnder(e.getX(), e.getY()); 30 | if (child != null && clicklistener != null) { 31 | clicklistener.onLongClick(child, recycleView.getChildAdapterPosition(child)); 32 | } 33 | } 34 | }); 35 | } 36 | 37 | @Override 38 | public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { 39 | View child = rv.findChildViewUnder(e.getX(), e.getY()); 40 | if (child != null && clicklistener != null && gestureDetector.onTouchEvent(e)) { 41 | clicklistener.onClick(child, rv.getChildAdapterPosition(child)); 42 | } 43 | 44 | return false; 45 | } 46 | 47 | @Override 48 | public void onTouchEvent(RecyclerView rv, MotionEvent e) { 49 | 50 | } 51 | 52 | @Override 53 | public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { 54 | 55 | } 56 | 57 | public interface ClickListener { 58 | void onClick(View view, int position); 59 | 60 | void onLongClick(View view, int position); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/sqlite/view/MainActivity.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.sqlite.view; 2 | 3 | import android.content.DialogInterface; 4 | import android.os.Bundle; 5 | import android.support.design.widget.CoordinatorLayout; 6 | import android.support.design.widget.FloatingActionButton; 7 | import android.support.v7.app.AlertDialog; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.support.v7.widget.DefaultItemAnimator; 10 | import android.support.v7.widget.LinearLayoutManager; 11 | import android.support.v7.widget.RecyclerView; 12 | import android.support.v7.widget.Toolbar; 13 | import android.text.TextUtils; 14 | import android.view.LayoutInflater; 15 | import android.view.View; 16 | import android.widget.EditText; 17 | import android.widget.TextView; 18 | import android.widget.Toast; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | import info.androidhive.sqlite.R; 24 | import info.androidhive.sqlite.database.DatabaseHelper; 25 | import info.androidhive.sqlite.database.model.Note; 26 | import info.androidhive.sqlite.utils.MyDividerItemDecoration; 27 | import info.androidhive.sqlite.utils.RecyclerTouchListener; 28 | 29 | public class MainActivity extends AppCompatActivity { 30 | private NotesAdapter mAdapter; 31 | private List notesList = new ArrayList<>(); 32 | private CoordinatorLayout coordinatorLayout; 33 | private RecyclerView recyclerView; 34 | private TextView noNotesView; 35 | 36 | private DatabaseHelper db; 37 | 38 | @Override 39 | protected void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | setContentView(R.layout.activity_main); 42 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 43 | setSupportActionBar(toolbar); 44 | 45 | coordinatorLayout = findViewById(R.id.coordinator_layout); 46 | recyclerView = findViewById(R.id.recycler_view); 47 | noNotesView = findViewById(R.id.empty_notes_view); 48 | 49 | db = new DatabaseHelper(this); 50 | 51 | notesList.addAll(db.getAllNotes()); 52 | 53 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 54 | fab.setOnClickListener(new View.OnClickListener() { 55 | @Override 56 | public void onClick(View view) { 57 | showNoteDialog(false, null, -1); 58 | } 59 | }); 60 | 61 | mAdapter = new NotesAdapter(this, notesList); 62 | RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext()); 63 | recyclerView.setLayoutManager(mLayoutManager); 64 | recyclerView.setItemAnimator(new DefaultItemAnimator()); 65 | recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16)); 66 | recyclerView.setAdapter(mAdapter); 67 | 68 | toggleEmptyNotes(); 69 | 70 | /** 71 | * On long press on RecyclerView item, open alert dialog 72 | * with options to choose 73 | * Edit and Delete 74 | * */ 75 | recyclerView.addOnItemTouchListener(new RecyclerTouchListener(this, 76 | recyclerView, new RecyclerTouchListener.ClickListener() { 77 | @Override 78 | public void onClick(View view, final int position) { 79 | } 80 | 81 | @Override 82 | public void onLongClick(View view, int position) { 83 | showActionsDialog(position); 84 | } 85 | })); 86 | } 87 | 88 | /** 89 | * Inserting new note in db 90 | * and refreshing the list 91 | */ 92 | private void createNote(String note) { 93 | // inserting note in db and getting 94 | // newly inserted note id 95 | long id = db.insertNote(note); 96 | 97 | // get the newly inserted note from db 98 | Note n = db.getNote(id); 99 | 100 | if (n != null) { 101 | // adding new note to array list at 0 position 102 | notesList.add(0, n); 103 | 104 | // refreshing the list 105 | mAdapter.notifyDataSetChanged(); 106 | 107 | toggleEmptyNotes(); 108 | } 109 | } 110 | 111 | /** 112 | * Updating note in db and updating 113 | * item in the list by its position 114 | */ 115 | private void updateNote(String note, int position) { 116 | Note n = notesList.get(position); 117 | // updating note text 118 | n.setNote(note); 119 | 120 | // updating note in db 121 | db.updateNote(n); 122 | 123 | // refreshing the list 124 | notesList.set(position, n); 125 | mAdapter.notifyItemChanged(position); 126 | 127 | toggleEmptyNotes(); 128 | } 129 | 130 | /** 131 | * Deleting note from SQLite and removing the 132 | * item from the list by its position 133 | */ 134 | private void deleteNote(int position) { 135 | // deleting the note from db 136 | db.deleteNote(notesList.get(position)); 137 | 138 | // removing the note from the list 139 | notesList.remove(position); 140 | mAdapter.notifyItemRemoved(position); 141 | 142 | toggleEmptyNotes(); 143 | } 144 | 145 | /** 146 | * Opens dialog with Edit - Delete options 147 | * Edit - 0 148 | * Delete - 0 149 | */ 150 | private void showActionsDialog(final int position) { 151 | CharSequence colors[] = new CharSequence[]{"Edit", "Delete"}; 152 | 153 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 154 | builder.setTitle("Choose option"); 155 | builder.setItems(colors, new DialogInterface.OnClickListener() { 156 | @Override 157 | public void onClick(DialogInterface dialog, int which) { 158 | if (which == 0) { 159 | showNoteDialog(true, notesList.get(position), position); 160 | } else { 161 | deleteNote(position); 162 | } 163 | } 164 | }); 165 | builder.show(); 166 | } 167 | 168 | 169 | /** 170 | * Shows alert dialog with EditText options to enter / edit 171 | * a note. 172 | * when shouldUpdate=true, it automatically displays old note and changes the 173 | * button text to UPDATE 174 | */ 175 | private void showNoteDialog(final boolean shouldUpdate, final Note note, final int position) { 176 | LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext()); 177 | View view = layoutInflaterAndroid.inflate(R.layout.note_dialog, null); 178 | 179 | AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(MainActivity.this); 180 | alertDialogBuilderUserInput.setView(view); 181 | 182 | final EditText inputNote = view.findViewById(R.id.note); 183 | TextView dialogTitle = view.findViewById(R.id.dialog_title); 184 | dialogTitle.setText(!shouldUpdate ? getString(R.string.lbl_new_note_title) : getString(R.string.lbl_edit_note_title)); 185 | 186 | if (shouldUpdate && note != null) { 187 | inputNote.setText(note.getNote()); 188 | } 189 | alertDialogBuilderUserInput 190 | .setCancelable(false) 191 | .setPositiveButton(shouldUpdate ? "update" : "save", new DialogInterface.OnClickListener() { 192 | public void onClick(DialogInterface dialogBox, int id) { 193 | 194 | } 195 | }) 196 | .setNegativeButton("cancel", 197 | new DialogInterface.OnClickListener() { 198 | public void onClick(DialogInterface dialogBox, int id) { 199 | dialogBox.cancel(); 200 | } 201 | }); 202 | 203 | final AlertDialog alertDialog = alertDialogBuilderUserInput.create(); 204 | alertDialog.show(); 205 | 206 | alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { 207 | @Override 208 | public void onClick(View v) { 209 | // Show toast message when no text is entered 210 | if (TextUtils.isEmpty(inputNote.getText().toString())) { 211 | Toast.makeText(MainActivity.this, "Enter note!", Toast.LENGTH_SHORT).show(); 212 | return; 213 | } else { 214 | alertDialog.dismiss(); 215 | } 216 | 217 | // check if user updating note 218 | if (shouldUpdate && note != null) { 219 | // update note by it's id 220 | updateNote(inputNote.getText().toString(), position); 221 | } else { 222 | // create new note 223 | createNote(inputNote.getText().toString()); 224 | } 225 | } 226 | }); 227 | } 228 | 229 | /** 230 | * Toggling list and empty notes view 231 | */ 232 | private void toggleEmptyNotes() { 233 | // you can check notesList.size() > 0 234 | 235 | if (db.getNotesCount() > 0) { 236 | noNotesView.setVisibility(View.GONE); 237 | } else { 238 | noNotesView.setVisibility(View.VISIBLE); 239 | } 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/sqlite/view/NotesAdapter.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.sqlite.view; 2 | 3 | /** 4 | * Created by ravi on 20/02/18. 5 | */ 6 | 7 | import android.content.Context; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.text.Html; 10 | import android.util.Log; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.TextView; 15 | 16 | import java.text.ParseException; 17 | import java.text.SimpleDateFormat; 18 | import java.util.Date; 19 | import java.util.List; 20 | 21 | import info.androidhive.sqlite.R; 22 | import info.androidhive.sqlite.database.model.Note; 23 | 24 | public class NotesAdapter extends RecyclerView.Adapter { 25 | 26 | private Context context; 27 | private List notesList; 28 | 29 | public class MyViewHolder extends RecyclerView.ViewHolder { 30 | public TextView note; 31 | public TextView dot; 32 | public TextView timestamp; 33 | 34 | public MyViewHolder(View view) { 35 | super(view); 36 | note = view.findViewById(R.id.note); 37 | dot = view.findViewById(R.id.dot); 38 | timestamp = view.findViewById(R.id.timestamp); 39 | } 40 | } 41 | 42 | 43 | public NotesAdapter(Context context, List notesList) { 44 | this.context = context; 45 | this.notesList = notesList; 46 | } 47 | 48 | @Override 49 | public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 50 | View itemView = LayoutInflater.from(parent.getContext()) 51 | .inflate(R.layout.note_list_row, parent, false); 52 | 53 | return new MyViewHolder(itemView); 54 | } 55 | 56 | @Override 57 | public void onBindViewHolder(MyViewHolder holder, int position) { 58 | Note note = notesList.get(position); 59 | 60 | holder.note.setText(note.getNote()); 61 | 62 | // Displaying dot from HTML character code 63 | holder.dot.setText(Html.fromHtml("•")); 64 | 65 | // Formatting and displaying timestamp 66 | holder.timestamp.setText(formatDate(note.getTimestamp())); 67 | } 68 | 69 | @Override 70 | public int getItemCount() { 71 | return notesList.size(); 72 | } 73 | 74 | /** 75 | * Formatting timestamp to `MMM d` format 76 | * Input: 2018-02-21 00:15:42 77 | * Output: Feb 21 78 | */ 79 | private String formatDate(String dateStr) { 80 | try { 81 | SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 82 | Date date = fmt.parse(dateStr); 83 | SimpleDateFormat fmtOut = new SimpleDateFormat("MMM d"); 84 | return fmtOut.format(date); 85 | } catch (ParseException e) { 86 | 87 | } 88 | 89 | return ""; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/drawable-hdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/drawable-mdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /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-xhdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/drawable-xhdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/drawable-xxhdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/drawable-xxxhdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 64 | 66 | 68 | 70 | 72 | 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 21 | 22 | 23 | 24 | 25 | 26 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/note_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 20 | 21 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/note_list_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 22 | 23 | 30 | 31 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /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/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/AndroidSQLite/2e72dcb104f8a2e03758e3da5cc6ae7d28e5783c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #455399 4 | #455399 5 | #00c6ae 6 | #999 7 | #89c3c3c3 8 | #858585 9 | #232323 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 16dp 4 | 10dp 5 | 26sp 6 | 120dp 7 | 20sp 8 | 10dp 9 | 20sp 10 | 30dp 11 | 40sp 12 | 14sp 13 | 18sp 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Notes 3 | Settings 4 | Notes 5 | No notes found! 6 | New Note 7 | Edit Note 8 | Enter your note! 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |