Membuat Aplikasi CRUD SQLite dengan Content Provider dan Circular Reveal Animation di Android Part2
Nov 11, 2017
Add Comment
di part pertama kita sudah melakukan persiapan untuk project ini, selanjutnya kita akan membuat class DBHelper di java
pertama buat dulu package data di java kemudian buat class EmployeeDbHelper dan masukan kode di bawah:
package com.giviews.employee.data;
import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by asus on 22/10/2017.
*/
public final class EmployeeDbHelper extends SQLiteOpenHelper{
public static final String LOG_TAG = EmployeeDbHelper.class.getSimpleName();
public static final String DATABASE_NAME= "employee.db";
private static final int DATABASE_VERSION = 1;
public EmployeeDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
//Create String to contains the SQL table
String SQL_CREATE_EMPLOYEES_TABLE = "CREATE TABLE " + EmployeeContract.EmployeeEntry.TABLE_NAME + "("
+ EmployeeContract.EmployeeEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ EmployeeContract.EmployeeEntry.COLUMN_FIRSTNAME + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_LASTNAME + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_TITLE + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_DEPARTMENT + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_CITY + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_PHONE + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_IMAGE + " BLOB NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_EMAIL + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_EMPLOYEE_GENDER + " INTEGER NOT NULL" + " );";
//EXECUTE THE SQL STATEMENT
db.execSQL(SQL_CREATE_EMPLOYEES_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
//on upgrade
}
}
import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by asus on 22/10/2017.
*/
public final class EmployeeDbHelper extends SQLiteOpenHelper{
public static final String LOG_TAG = EmployeeDbHelper.class.getSimpleName();
public static final String DATABASE_NAME= "employee.db";
private static final int DATABASE_VERSION = 1;
public EmployeeDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
//Create String to contains the SQL table
String SQL_CREATE_EMPLOYEES_TABLE = "CREATE TABLE " + EmployeeContract.EmployeeEntry.TABLE_NAME + "("
+ EmployeeContract.EmployeeEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ EmployeeContract.EmployeeEntry.COLUMN_FIRSTNAME + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_LASTNAME + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_TITLE + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_DEPARTMENT + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_CITY + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_PHONE + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_IMAGE + " BLOB NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_EMAIL + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_EMPLOYEE_GENDER + " INTEGER NOT NULL" + " );";
//EXECUTE THE SQL STATEMENT
db.execSQL(SQL_CREATE_EMPLOYEES_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
//on upgrade
}
}
pada kelas DbHelper di atas kita sudah membuat database dan tablenya.
Sekarang kita buat class baru dengan nama EmployeeContract dan masukan kode berikut:
package com.giviews.employee.data;
import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by asus on 22/10/2017.
*/
public final class EmployeeDbHelper extends SQLiteOpenHelper{
public static final String LOG_TAG = EmployeeDbHelper.class.getSimpleName();
public static final String DATABASE_NAME = "employee.db";
private static final int DATABASE_VERSION = 1;
public EmployeeDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
//Create String to contains the SQL table
String SQL_CREATE_EMPLOYEES_TABLE = "CREATE TABLE " + EmployeeContract.EmployeeEntry.TABLE_NAME + "("
+ EmployeeContract.EmployeeEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ EmployeeContract.EmployeeEntry.COLUMN_FIRSTNAME + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_LASTNAME + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_TITLE + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_DEPARTMENT + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_CITY + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_PHONE + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_IMAGE + " BLOB NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_EMAIL + " TEXT NOT NULL, "
+ EmployeeContract.EmployeeEntry.COLUMN_EMPLOYEE_GENDER + " INTEGER NOT NULL" + " );";
//EXECUTE THE SQL STATEMENT
db.execSQL(SQL_CREATE_EMPLOYEES_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
//on upgrade
}
}
kemudian buat lagi class baru dengan nama EmployeeProvider dan masukan kode berikut:
package com.giviews.employee.data;
import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.util.Log;
import java.util.HashMap;
/**
* Created by asus on 24/10/2017.
*/
public class EmployeeProvider extends ContentProvider {
public static final String LOG_TAG = EmployeeProvider.class.getSimpleName();
private static final int EMPLOYEES = 100;
private static final int EMPLOYEE_ID = 101;
private static final int SEARCH_SUGGEST = 102;
private static final HashMap<String, String> SEARCH_SUGGEST_PROJECTION_MAP;
static {
SEARCH_SUGGEST_PROJECTION_MAP = new HashMap<String, String>();
SEARCH_SUGGEST_PROJECTION_MAP.put(EmployeeContract.EmployeeEntry._ID, EmployeeContract.EmployeeEntry._ID);
SEARCH_SUGGEST_PROJECTION_MAP.put(SearchManager.SUGGEST_COLUMN_TEXT_1, EmployeeContract.EmployeeEntry.COLUMN_FIRSTNAME + " AS " + SearchManager.SUGGEST_COLUMN_TEXT_1);
SEARCH_SUGGEST_PROJECTION_MAP.put(SearchManager.SUGGEST_COLUMN_TEXT_2, EmployeeContract.EmployeeEntry.COLUMN_LASTNAME + " AS " + SearchManager.SUGGEST_COLUMN_TEXT_2);
SEARCH_SUGGEST_PROJECTION_MAP.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, EmployeeContract.EmployeeEntry._ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
}
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
public static final Uri SEARCH_SUGGEST_URI = Uri.parse("content://" + EmployeeContract.CONTENT_ATHORITY + "/" + EmployeeContract.PATH_EMPLOYEES + "/" + SearchManager.SUGGEST_URI_PATH_QUERY);
static {
sUriMatcher.addURI(EmployeeContract.CONTENT_ATHORITY, EmployeeContract.PATH_EMPLOYEES, EMPLOYEES);
sUriMatcher.addURI(EmployeeContract.CONTENT_ATHORITY, EmployeeContract.PATH_EMPLOYEES + "/#", EMPLOYEE_ID);
}
public EmployeeProvider(){
sUriMatcher.addURI(EmployeeContract.CONTENT_ATHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
sUriMatcher.addURI(EmployeeContract.CONTENT_ATHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
}
private EmployeeDbHelper mDbHelper;
@Override
public boolean onCreate() {
mDbHelper = new EmployeeDbHelper(getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
SQLiteDatabase database = mDbHelper.getReadableDatabase();
Cursor cursor;
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(EmployeeContract.EmployeeEntry.TABLE_NAME);
int match = sUriMatcher.match(uri);
switch (match) {
case SEARCH_SUGGEST:
selectionArgs = new String[] { "%" + selectionArgs[0] + "%", "%" + selectionArgs[0] + "%"};
queryBuilder.setProjectionMap(SEARCH_SUGGEST_PROJECTION_MAP);
cursor = queryBuilder.query(database, projection, selection, selectionArgs, null, null, sortOrder);
break;
case EMPLOYEES:
cursor = database.query(EmployeeContract.EmployeeEntry.TABLE_NAME, projection, selection, selectionArgs,
null, null, sortOrder);
break;
case EMPLOYEE_ID:
selection = EmployeeContract.EmployeeEntry._ID + "=?";
selectionArgs = new String[] {String.valueOf(ContentUris.parseId(uri))};
cursor = database.query(EmployeeContract.EmployeeEntry.TABLE_NAME, projection, selection, selectionArgs,
null, null, sortOrder);
break;
default:
throw new IllegalArgumentException("Cannot query unknown uri" + uri);
}
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
final int match = sUriMatcher.match(uri);
switch (match) {
case EMPLOYEES:
return insertEmployee(uri, contentValues);
default:
throw new IllegalArgumentException("Inserted is not supported for " + uri);
}
}
private Uri insertEmployee(Uri uri, ContentValues values) {
String firstname = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_FIRSTNAME);
if (firstname == null) {
throw new IllegalArgumentException("Employee require a firstname");
}
String lastname = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_LASTNAME);
if (lastname == null) {
throw new IllegalArgumentException("Employee requires a lastname");
}
String department = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_DEPARTMENT);
if (department == null) {
throw new IllegalArgumentException("Employee requires a lastname");
}
String title = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_TITLE);
if (title == null) {
throw new IllegalArgumentException("Employee requires a title");
}
String city = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_CITY);
if (city == null) {
throw new IllegalArgumentException("Employee requires a city");
}
String phone = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_PHONE);
if (phone == null) {
throw new IllegalArgumentException("Employee requires a phone number");
}
String email = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_EMAIL);
if (email == null) {
throw new IllegalArgumentException("Employee requires an email");
}
//check gender is valid
Integer gender = values.getAsInteger(EmployeeContract.EmployeeEntry.COLUMN_EMPLOYEE_GENDER);
if (gender == null || !EmployeeContract.EmployeeEntry.isValidGender(gender)) {
throw new IllegalArgumentException("Employee requires valid gender");
}
//get writable database
SQLiteDatabase database = mDbHelper.getWritableDatabase();
//Insert new Employee with given values
Long id = database.insert(EmployeeContract.EmployeeEntry.TABLE_NAME, null, values);
if (id == -1) {
Log.e(LOG_TAG, "Failed to insert row for" + uri);
return null;
}
getContext().getContentResolver().notifyChange(uri, null);
return ContentUris.withAppendedId(uri, id);
}
@Override
public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) {
final int match = sUriMatcher.match(uri);
switch (match) {
case EMPLOYEES:
return updateEmployee(uri, contentValues, selection, selectionArgs);
case EMPLOYEE_ID:
selection = EmployeeContract.EmployeeEntry._ID + "=?";
selectionArgs = new String[] {String.valueOf(ContentUris.parseId(uri))};
return updateEmployee(uri, contentValues, selection, selectionArgs);
default:
throw new IllegalArgumentException("Update is not supported for " + uri);
}
}
private int updateEmployee(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
if (values.containsKey(EmployeeContract.EmployeeEntry.COLUMN_FIRSTNAME)){
String firstname = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_FIRSTNAME);
if (firstname == null) {
throw new IllegalArgumentException("Employee requires a firstname");
}
}
if (values.containsKey(EmployeeContract.EmployeeEntry.COLUMN_LASTNAME)){
String lastname = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_LASTNAME);
if (lastname == null) {
throw new IllegalArgumentException("Employess requires a lastname");
}
}
if (values.containsKey(EmployeeContract.EmployeeEntry.COLUMN_TITLE)){
String title = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_TITLE);
if (title == null) {
throw new IllegalArgumentException("Employee requires a title");
}
}
if (values.containsKey(EmployeeContract.EmployeeEntry.COLUMN_DEPARTMENT)) {
String department = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_DEPARTMENT);
if (department == null) {
throw new IllegalArgumentException("Employee requires a department");
}
}
if (values.containsKey(EmployeeContract.EmployeeEntry.COLUMN_CITY)) {
String city = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_CITY);
if (city == null) {
throw new IllegalArgumentException("Employee requires a city");
}
}
if (values.containsKey(EmployeeContract.EmployeeEntry.COLUMN_PHONE)) {
String phone = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_PHONE);
if (phone == null) {
throw new IllegalArgumentException("Employee requires a phone number");
}
}
if (values.containsKey(EmployeeContract.EmployeeEntry.COLUMN_EMAIL)) {
String email = values.getAsString(EmployeeContract.EmployeeEntry.COLUMN_EMAIL);
if (email == null) {
throw new IllegalArgumentException("Employee require an email");
}
}
if (values.containsKey(EmployeeContract.EmployeeEntry.COLUMN_EMPLOYEE_GENDER)) {
Integer gender = values.getAsInteger(EmployeeContract.EmployeeEntry.COLUMN_EMPLOYEE_GENDER);
if (gender == null || !EmployeeContract.EmployeeEntry.isValidGender(gender)) {
throw new IllegalArgumentException("Employee require a valid gender");
}
}
if (values.size() == 0) {
return 0;
}
SQLiteDatabase database = mDbHelper.getWritableDatabase();
int rowsUpdated = database.update(EmployeeContract.EmployeeEntry.TABLE_NAME, values, selection, selectionArgs);
if (rowsUpdated != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return rowsUpdated;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase database = mDbHelper.getWritableDatabase();
int rowsDeleted;
final int match = sUriMatcher.match(uri);
switch (match) {
case EMPLOYEES:
//delete all rows
rowsDeleted = database.delete(EmployeeContract.EmployeeEntry.TABLE_NAME, selection, selectionArgs);
break;
case EMPLOYEE_ID:
selection = EmployeeContract.EmployeeEntry._ID + "=?";
selectionArgs = new String[] {String.valueOf(ContentUris.parseId(uri))};
rowsDeleted = database.delete(EmployeeContract.EmployeeEntry.TABLE_NAME, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Deletion is not support for " + uri);
}
if (rowsDeleted != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return rowsDeleted;
}
@Override
public String getType(Uri uri) {
final int match = sUriMatcher.match(uri);
switch (match) {
case EMPLOYEES:
return EmployeeContract.EmployeeEntry.CONTENT_LIST_TYPE;
case EMPLOYEE_ID:
return EmployeeContract.EmployeeEntry.CONTENT_ITEM_TYPE;
case SEARCH_SUGGEST:
return null;
default:
throw new IllegalArgumentException("Unknown URI " + uri + " with match " + match);
}
}
}
pada class EmployeeProvider diatas kita sudah membuat fungsi untuk CRUD nya yaitu fungsi untuk menambahkan data, merubah data, memparsing data dan menghapus data.
setelah kita membuat class-class diatas selanjutnya kita akan membuat desain antarmuka untuk aplikasi kita
pertama kita buat layout activity_employee seperti berikut:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.giviews.employee.EmployeeActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_setting"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
android:theme="@style/AppTheme.AppBarOverlay" />
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/toolbar_setting">
</ListView>
<!--Empty List-->
<RelativeLayout
android:id="@+id/empty_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<ImageView
android:id="@+id/img"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/ic_notifications"
android:layout_centerInParent="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Belum Ada Data"
android:gravity="center"
android:layout_below="@+id/img" />
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:src="@drawable/ic_person_add"/>
</RelativeLayout>
selanjutnya buat layout activity_editor seperti berikut:
<?xml version="1.0" encoding="utf-8"?>
<com.hendraanggrian.widget.RevealFrameLayout
android:id="@+id/revealLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.giviews.employee.EmployeeEditor">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_setting"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
android:theme="@style/AppTheme.AppBarOverlay" />
<android.support.design.widget.CoordinatorLayout
android:layout_marginTop="56dp"
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
android:orientation="vertical">
<ImageView
android:id="@+id/profileImageView"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:background="@color/colorAccent"
android:scaleType="centerCrop"
android:src="@drawable/ic_account_circle_black"/>
<Button
android:layout_margin="10dp"
android:layout_gravity="center"
android:id="@+id/pickImage"
android:layout_width="90dp"
android:layout_height="wrap_content"
android:text="Select Image" />
<EditText
android:id="@+id/firstName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Fist Name"/>
<EditText
android:id="@+id/lastName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Last Name"/>
<EditText
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Title"/>
<EditText
android:id="@+id/department"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Department"/>
<EditText
android:id="@+id/city"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="City"/>
<EditText
android:id="@+id/phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:hint="Phone Number"/>
<EditText
android:id="@+id/email"
android:inputType="textEmailAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email"/>
<Spinner
android:id="@+id/spinner_gender"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:paddingRight="16dp"
android:spinnerMode="dropdown"/>
</LinearLayout>
</ScrollView>
</android.support.design.widget.CoordinatorLayout>
</com.hendraanggrian.widget.RevealFrameLayout>
selanjutnya buat layout list_item untuk menampilkan data listviewnya:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<TextView
android:id="@+id/firstname"
android:textStyle="bold"
android:textSize="17dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/lastname"
android:textStyle="bold"
android:layout_marginLeft="5dp"
android:textSize="17dp"
android:layout_toEndOf="@+id/firstname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/firstname" />
<TextView
android:id="@+id/titleview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/lastname"/>
</RelativeLayout>
sampai disini dulu part ke2 nya akan kita lanjutkan di part ke 3 memfungsikan layout yang sudah kita buat
0 Response to "Membuat Aplikasi CRUD SQLite dengan Content Provider dan Circular Reveal Animation di Android Part2"
Post a Comment