Artikel kali ini penulis membahas mengenai aplikasi E-laundry
, Aplikasi ini masih belum selesai anggap saja masih setengah dari pengerjaan karna sampai sekarang client
belum ada kejelasan apakah mau dilanjutkan apa tidak, jadi terpaksa saya jadikan artikel, sekaligus saya pelajari lagi alur dari code
aplikasi, berharap aplikasi e-laundry
dilanjutkan pengerjaannya dari client
tersebut.
Vidio belum tersedia…
Add Dependencies ... (Still Under Development)
Anda tambahkan modul dependencies
dibagian gradle
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'com.google.firebase:firebase-analytics:17.2.0'
implementation 'com.google.firebase:firebase-auth:19.1.0'
implementation 'com.google.android.gms:play-services-auth:17.0.0'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.12.1'
implementation 'com.google.android.gms:play-services-maps:17.0.0'
implementation 'com.google.android.gms:play-services-location:17.0.0'
implementation 'com.google.android.libraries.places:places:2.2.0'
Add URL API
Masukan URL API
dibagian Build Types
, Anda buat dibagian type debug
dan dibagian type release
buildConfigField "String", "SERVER_URL", 'URL_API_YOU'
Add Model Package ... (Still Under Development)
Anda Tambahkan class
model Konsumen
, ResultLogin
, ResultSignup
, ... (Still Under Development)
Model Konsumen
class Konsumen {
@SerializedName("id")
@Expose
val id: String? = null
@SerializedName("nama")
@Expose
val nama: String? = null
@SerializedName("alamat")
@Expose
val alamat: String? = null
@SerializedName("telp")
@Expose
val telp: String? = null
@SerializedName("email")
@Expose
val email: String? = null
@SerializedName("password")
@Expose
val password: String? = null
}
Model ResultLogin
class ResultLogin {
@SerializedName("status")
@Expose
val isStatus: Boolean = false
@SerializedName("user_login")
@Expose
val user_login: String? = null
@SerializedName("token")
@Expose
val token: String? = null
@SerializedName("result")
@Expose
val result: Konsumen? = null
}
Model ResultSignup
class ResultSignup {
@SerializedName("status")
@Expose
val isStatus: Boolean = false
}
Jika Anda sudah membuat model selanjutnya anda buat untuk menghubungkan API
, untuk menghubungkan digunakan modul retrofit
yang anda sudah tambahkan dibagian dependencies
Add Data Service ... (Still Under Development)
Anda buat data service
yang diambil dari setiap Part API
anda, kemudian anda tentukan tindakan yang digunakan apakah POST, GET, PUT, UPDATE
atau yang lainnya sesuaikan berdasarkan bagian API
interface DataService {
@FormUrlEncoded
@POST("login")
fun getLogin(
@Field("email") email: String,
@Field("password") password: String
): Call<ResultLogin>
@FormUrlEncoded
@POST("signup")
fun getSignup(
@Field("nama") nama: String,
@Field("alamat") alamat: String,
@Field("telp") telp: String,
@Field("email") email: String,
@Field("password") password: String
): Call<ResultSignup>
}
Add Data Provider ... (Still Under Development)
Anda buat data provider
di class ini digunakan untuk menghubungkan antara API
dengan melakukan convert
munggunakan modul retrofit
dari sebelumnya dalam bentuk JSON
ke dalam bentuk object
berupa attribut
supaya bisa mudah di proses lebih mudah
class DataProvider(token: String) {
private val retrofit: Retrofit
private var mytoken: String? = null
private val dataService: DataService
init {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.connectTimeout(60, TimeUnit.SECONDS)
.addInterceptor(interceptor).build()
val gson = GsonBuilder()
.setLenient()
.create()
retrofit = Retrofit.Builder()
.baseUrl(BuildConfig.SERVER_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
dataService = retrofit.create(DataService::class.java)
setMytoken(token)
}
private fun setMytoken(mytoken: String) {
this.mytoken = mytoken
}
fun getLogin(email: String, password: String): Call<ResultLogin> {
return dataService.getLogin(email, password)
}
fun getSignup(
nama: String,
alamat: String,
mobile_number: String,
email: String,
password: String
): Call<ResultSignup> {
return dataService.getSignup(nama, alamat, mobile_number, email, password)
}
companion object {
fun instance(token: String): DataProvider {
return DataProvider(token)
}
}
}
Add Local Data
Menampung data sementara dari setiap model, dalam kasus ini menyesuaikan dengan data API sesuai respon, contohnya seperti data pengguna yang login, class yang digunakan untuk penyimpanan sementara class SharedPreferences
class LocalData(private val context: Context) {
private fun setting(): SharedPreferences {
return context.getSharedPreferences(PREFS_NAME, 0)
}
private fun editor(): SharedPreferences.Editor {
return setting().edit()
}
fun setData(key: String, data: String) {
val editor = editor()
editor.putString(key, data)
editor.commit()
}
fun getData(key: String): String {
return setting().getString(key, "").toString()
}
fun getData(key: String, def: Int): Int {
return setting().getInt(key, def)
}
companion object {
private val PREFS_NAME = "elaundry"
fun L(context: Context): LocalData {
return LocalData(context)
}
}
}
Download Resource File
Anda download
file
yang berisi data class
dari tamplate
yang sudah diupdate dan file
resource
, Download Archive E-laundry
Jika Anda sudah memasukan file yang anda download dibagian aplikasi sesuai langkah di video selanjutnya anda buat beberapa class utama
Buat Class Login
Anda buat activity
login
yang digunakan konsumen dalam masuk ke aplikasi elaundry
dengan aman
public class LoginActivity extends AppCompatActivity {
private static final String TAG = "LoginActivity";
private static final int REQUEST_SIGNUP = 0;
private boolean isLogin = false;
ProgressBar _login_progress;
EditText _emailText;
EditText _passwordText;
Button _loginButton;
TextView link_forgotpassword;
LinearLayout _signupLink;
//name strings
String lastName = "";
String firstName = "";
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
this.getSupportActionBar().hide();
} catch (NullPointerException ignored) {
}
setContentView(R.layout.activity_login);
/*black icons on top bar like battery etc*/
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
_login_progress = findViewById(R.id.login_progress);
_emailText = findViewById(R.id.input_email);
_passwordText = findViewById(R.id.input_password);
_loginButton = findViewById(R.id.btn_login);
_signupLink = findViewById(R.id.link_signup);
link_forgotpassword = findViewById(R.id.link_forgotpassword);
link_forgotpassword.setOnClickListener(v -> {
Intent intent = new Intent(LoginActivity.this, ResetPasswordActivity.class);
startActivity(intent);
});
_loginButton.setOnClickListener(v -> login());
_signupLink.setOnClickListener(v -> {
// Start the ResultSignup activity
startActivity(new Intent(LoginActivity.this, SignUpActivity.class));
});
}
public void login() {
Log.d(TAG, "ResultLogin");
if (!validate()) {
onLoginFailed();
return;
}
_loginButton.setEnabled(false);
if (isLogin) {
return;
}
_login_progress.setVisibility(View.VISIBLE);
_login_progress.setProgress(10);
isLogin = true;
String email = _emailText.getText().toString();
String password = _passwordText.getText().toString();
DataProvider.Companion.instance("").getLogin(email, password).enqueue(new Callback<ResultLogin>() {
@Override
public void onResponse(@NotNull Call<ResultLogin> call, @NotNull Response<ResultLogin> response) {
_login_progress.setProgress(50);
if (response.code() == 200) {
ResultLogin resultLogin = response.body();
if (resultLogin != null && resultLogin.isStatus()) {
Log.e("getLaundry", "" + resultLogin.getResult().getNama());
LocalData.Companion.L(getBaseContext()).setData("token", resultLogin.getToken());
LocalData.Companion.L(getBaseContext()).setData("user_login", resultLogin.getUser_login());
LocalData.Companion.L(getBaseContext()).setData("nama", resultLogin.getResult().getNama());
LocalData.Companion.L(getBaseContext()).setData("alamat", resultLogin.getResult().getAlamat());
LocalData.Companion.L(getBaseContext()).setData("telp", resultLogin.getResult().getTelp());
LocalData.Companion.L(getBaseContext()).setData("email", resultLogin.getResult().getEmail());
stopProgress(new onCallback() {
@Override
public void onRun() {
isLogin = false;
startActivity(new Intent(getBaseContext(), MainActivity.class));
onLoginSuccess();
}
});
} else {
stopProgress(() -> {
isLogin = false;
AlertDialogBox.INSTANCE.Alert(LoginActivity.this, "Username or Password not valid");
onLoginFailed();
});
}
} else {
stopProgress(() -> {
isLogin = false;
AlertDialogBox.INSTANCE.Alert(LoginActivity.this, "Username or Password not valid");
onLoginFailed();
});
}
}
@Override
public void onFailure(@NotNull Call<ResultLogin> call, @NotNull Throwable t) {
Log.e("getLaundry", "" + t.getMessage());
stopProgress(() -> {
isLogin = false;
AlertDialogBox.INSTANCE.Alert(LoginActivity.this, "Error with connection");
});
}
});
}
private String getfirstname(String name) {
if (name.split("\\w+").length > 1) {
lastName = name.substring(name.lastIndexOf(" ") + 1);
firstName = name.substring(0, name.lastIndexOf(' '));
return firstName;
} else {
firstName = name;
return firstName;
}
}
private boolean havelastname(String name) {
if (name.split("\\w+").length > 1) {
lastName = name.substring(name.lastIndexOf(" ") + 1);
firstName = name.substring(0, name.lastIndexOf(' '));
return true;
} else {
firstName = name;
return false;
}
}
@SuppressLint("MissingSuperCall")
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_SIGNUP) {
if (resultCode == RESULT_OK) {
// TODO: Implement successful signup logic here
// By default we just finish the Activity and log them in automatically
this.finish();
}
}
}
@Override
public void onBackPressed() {
// disable going back to the MainActivityStudent
moveTaskToBack(true);
}
public void onLoginSuccess() {
_loginButton.setEnabled(true);
finish();
}
public void onLoginFailed() {
_loginButton.setEnabled(true);
}
public boolean validate() {
boolean valid = true;
String email = _emailText.getText().toString();
String password = _passwordText.getText().toString();
if (email.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
_emailText.setError("enter a valid email address");
valid = false;
} else {
_emailText.setError(null);
}
if (password.isEmpty() || password.length() < 4 || password.length() > 10) {
_passwordText.setError("between 4 and 10 alphanumeric characters");
valid = false;
} else {
_passwordText.setError(null);
}
return valid;
}
private void stopProgress(final onCallback callback) {
new Handler().postDelayed(() -> _login_progress.setProgress(100), 5000);
new Handler().postDelayed(() -> {
_login_progress.setVisibility(View.GONE);
callback.onRun();
}, 3000);
}
private interface onCallback {
void onRun();
}
}
Buat Class SignUp
Digunakan untuk registrasi atau daftar konsumen baru pada aplikasi e-laundry
public class SignUpActivity extends AppCompatActivity {
private static final String TAG = "SignupActivity";
EditText _phonenumberText, _emailText, _passwordText, _nameText, _addressText;
Button _signupButton;
ImageView backbtn;
String namest, emailst, passst, addressst, phonenumber;
TextView titletxt, desctxt;
LinearLayout userinfo_tab, _loginLink, namell, addressll, emailll, passwordll, phonenumberll;
int step = 1;
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
_passwordText = findViewById(R.id.input_password);
_emailText = findViewById(R.id.input_email);
_nameText = findViewById(R.id.input_name);
_addressText = findViewById(R.id.input_address);
_signupButton = findViewById(R.id.btn_signup);
_phonenumberText = findViewById(R.id.input_phonenumber);
_loginLink = findViewById(R.id.link_login);
namell = findViewById(R.id.namell);
addressll = findViewById(R.id.addressll);
emailll = findViewById(R.id.emailll);
passwordll = findViewById(R.id.passwordll);
phonenumberll = findViewById(R.id.phonenumberll);
titletxt = findViewById(R.id.titletxt);
desctxt = findViewById(R.id.desctxt);
userinfo_tab = findViewById(R.id.userinfo_tab);
backbtn = findViewById(R.id.backbtn);
hideall();
namell.setVisibility(View.VISIBLE);
/*Setting on click listeners*/
backbtn.setOnClickListener(v -> finish());
_signupButton.setOnClickListener(v -> {
if (step == 1) {
namest = _nameText.getText().toString();
if (namest.isEmpty()) {
Toast.makeText(SignUpActivity.this, "Please write your name!", Toast.LENGTH_SHORT).show();
} else {
namell.setVisibility(View.GONE);
addressll.setVisibility(View.VISIBLE);
titletxt.setText("Create Address");
desctxt.setText("enter your address below.");
step++;
}
} else if (step == 2) {
addressst = _addressText.getText().toString();
if (addressst.isEmpty()) {
Toast.makeText(SignUpActivity.this, "Please write your address!", Toast.LENGTH_SHORT).show();
} else {
addressll.setVisibility(View.GONE);
emailll.setVisibility(View.VISIBLE);
titletxt.setText("Create Email");
desctxt.setText("enter your email below.");
step++;
}
} else if (step == 3) {
emailst = _emailText.getText().toString();
if (emailst.isEmpty()) {
Toast.makeText(SignUpActivity.this, "Please write your email!", Toast.LENGTH_SHORT).show();
} else {
emailll.setVisibility(View.GONE);
passwordll.setVisibility(View.VISIBLE);
titletxt.setText("Create Password");
desctxt.setText("Your password must have atleast one symbol & 4 or more characters.");
step++;
}
} else if (step == 4) {
passst = _passwordText.getText().toString();
if (passst.isEmpty()) {
Toast.makeText(SignUpActivity.this, "Please write your password!", Toast.LENGTH_SHORT).show();
} else {
passwordll.setVisibility(View.GONE);
phonenumberll.setVisibility(View.VISIBLE);
titletxt.setText("Create Mobile Number");
desctxt.setText("Enter your mobile number.");
step++;
}
} else if (step == 5) {
phonenumber = _phonenumberText.getText().toString();
if (phonenumber.isEmpty()) {
Toast.makeText(SignUpActivity.this, "Please write your mobile number!", Toast.LENGTH_SHORT).show();
} else {
phonenumberll.setVisibility(View.GONE);
titletxt.setText("Let's Get Started");
_signupButton.setText("FINISH");
step++;
}
} else if (step == 6) {
signup();
}
});
_loginLink.setOnClickListener(v -> {
// Finish the registration screen and return to the ResultLogin activity
finish();
});
}
private void hideall() {
//removing all the edit text will be opened one by one
namell.setVisibility(View.GONE);
addressll.setVisibility(View.GONE);
emailll.setVisibility(View.GONE);
passwordll.setVisibility(View.GONE);
phonenumberll.setVisibility(View.GONE);
}
public void signup() {
Log.d(TAG, "ResultSignup");
_signupButton.setEnabled(false);
final ProgressDialog progressDialog = new ProgressDialog(SignUpActivity.this);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Save process...");
progressDialog.show();
String name = _nameText.getText().toString();
String address = _addressText.getText().toString();
String email = _emailText.getText().toString();
String password = _passwordText.getText().toString();
String mobilephone = _phonenumberText.getText().toString();
DataProvider.Companion.instance("").getSignup(
name, address, mobilephone, email, password
)
.enqueue(new Callback<ResultSignup>() {
@Override
public void onResponse(@NotNull Call<ResultSignup> call, @NotNull Response<ResultSignup> response) {
if (response.code() == 200) {
ResultSignup result = response.body();
if (result != null && result.isStatus()) {
new android.os.Handler().postDelayed(
() -> {
onSignupSuccess();
progressDialog.dismiss();
}, 3000);
} else {
onSignupFailed();
progressDialog.dismiss();
}
}
}
@Override
public void onFailure(@NotNull Call<ResultSignup> call, @NotNull Throwable t) {
Log.e("getLaundry", "" + t.getMessage());
}
});
}
public void onSignupSuccess() {
_signupButton.setEnabled(true);
setResult(RESULT_OK, null);
Intent intent = new Intent(SignUpActivity.this, LoginActivity.class);
startActivity(intent);
finish();
AlertDialogBox.INSTANCE.Alert(SignUpActivity.this, "Saved successfully");
}
public void onSignupFailed() {
Toast.makeText(getBaseContext(), "Login failed", Toast.LENGTH_LONG).show();
_signupButton.setEnabled(true);
}
public boolean validate() {
boolean valid = true;
String name = _nameText.getText().toString();
String email = _emailText.getText().toString();
String password = _passwordText.getText().toString();
if (name.isEmpty() || name.length() < 3) {
_nameText.setError("at least 3 characters");
valid = false;
} else {
_nameText.setError(null);
}
if (email.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
_emailText.setError("enter a valid email address");
valid = false;
} else {
_emailText.setError(null);
}
if (password.isEmpty() || password.length() < 4 || password.length() > 10) {
_passwordText.setError("between 4 and 10 alphanumeric characters");
valid = false;
} else {
_passwordText.setError(null);
}
return valid;
}
}
Buat Class Reset Password ... (Still Under Development)
Digunakan untuk reset password pengguna pada konsumen
public class ResetPasswordActivity extends AppCompatActivity {
private static final String TAG = "ResetPasswordActivity";
private EditText inputEmail;
private Button btnReset;
private TextView btnBack;
private ProgressBar progressBar;
private ImageView backbtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reset_password);
inputEmail = findViewById(R.id.email);
btnReset = findViewById(R.id.btn_reset_password);
btnBack = findViewById(R.id.link_login);
progressBar = findViewById(R.id.progressBar);
backbtn = findViewById(R.id.backbtn);
backbtn.setOnClickListener(v -> finish());
btnBack.setOnClickListener(v -> finish());
btnReset.setOnClickListener(v -> {
String email = inputEmail.getText().toString().trim();
if (TextUtils.isEmpty(email)) {
AlertDialogBox.INSTANCE.Alert(ResetPasswordActivity.this, "Enter your registered email");
} else {
resetEmail();
}
progressBar.setVisibility(View.VISIBLE);
});
}
private void resetEmail() {
Toast.makeText(this, "Still under development", Toast.LENGTH_SHORT).show();
}
Buat Class MainActivity
Diclass ini sebagai transaksi untuk memilih jenis pakaian yang akan di laundry sekaligus menampilkan jumlah biaya laundry
public class MainActivity extends AppCompatActivity implements LeftMenuAdapter.onItemSelectedListener,
ServicesCartImp, ServicesCartDialog.ShopCartDialogImp {
private final static String TAG = "MainActivity";
private RecyclerView leftMenu;
private RecyclerView rightMenu;
private TextView headerView;
private LinearLayout headerLayout;
private ServiceMenu headMenu;
private LeftMenuAdapter leftAdapter;
private RightServiceAdapter rightAdapter;
private ArrayList<ServiceMenu> serviceMenuList;
private boolean leftClickType = false;
private ServicesCart servicesCart;
private ImageView servicesCartView;
private FrameLayout servicesCartLayout;
private TextView totalPriceTextView;
private TextView totalPriceNumTextView;
private RelativeLayout mainLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
initAdapter();
}
private void initView() {
mainLayout = findViewById(R.id.main_layout);
leftMenu = findViewById(R.id.left_menu);
rightMenu = findViewById(R.id.right_menu);
headerView = findViewById(R.id.right_menu_tv);
headerLayout = findViewById(R.id.right_menu_item);
servicesCartView = findViewById(R.id.services_cart);
servicesCartLayout = findViewById(R.id.services_cart_layout);
totalPriceTextView = findViewById(R.id.services_cart_total_tv);
totalPriceNumTextView = findViewById(R.id.services_cart_total_num);
leftMenu.setLayoutManager(new LinearLayoutManager(this));
rightMenu.setLayoutManager(new LinearLayoutManager(this));
rightMenu.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NotNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(@NotNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (!recyclerView.canScrollVertically(1)) {
showHeadView();
return;
}
View underView = null;
if (dy > 0)
underView = rightMenu.findChildViewUnder(headerLayout.getX(), headerLayout.getMeasuredHeight() + 1);
else
underView = rightMenu.findChildViewUnder(headerLayout.getX(), 0);
if (underView != null && underView.getContentDescription() != null) {
int position = Integer.parseInt(underView.getContentDescription().toString());
ServiceMenu menu = rightAdapter.getMenuOfMenuByPosition(position);
if (leftClickType || !menu.getMenuName().equals(headMenu.getMenuName())) {
if (dy > 0 && headerLayout.getTranslationY() <= 1 && headerLayout.getTranslationY() >= -1 * headerLayout.getMeasuredHeight() * 4 / 5 && !leftClickType) {// underView.getTop()>9
int dealtY = underView.getTop() - headerLayout.getMeasuredHeight();
headerLayout.setTranslationY(dealtY);
// Log.e(TAG, "onScrolled: "+headerLayout.getTranslationY()+" "+headerLayout.getBottom()+" - "+headerLayout.getMeasuredHeight() );
} else if (dy < 0 && headerLayout.getTranslationY() <= 0 && !leftClickType) {
headerView.setText(menu.getMenuName());
int dealtY = underView.getBottom() - headerLayout.getMeasuredHeight();
headerLayout.setTranslationY(dealtY);
// Log.e(TAG, "onScrolled: "+headerLayout.getTranslationY()+" "+headerLayout.getBottom()+" - "+headerLayout.getMeasuredHeight() );
} else {
headerLayout.setTranslationY(0);
headMenu = menu;
headerView.setText(headMenu.getMenuName());
for (int i = 0; i < serviceMenuList.size(); i++) {
if (serviceMenuList.get(i) == headMenu) {
leftAdapter.setSelectedNum(i);
break;
}
}
if (leftClickType) leftClickType = false;
Log.e(TAG, "onScrolled: " + menu.getMenuName());
}
}
}
}
});
servicesCartLayout.setOnClickListener(view -> showCart(view));
}
private void initData() {
servicesCart = new ServicesCart();
serviceMenuList = new ArrayList<>();
ArrayList<Services> menu1 = new ArrayList<>();
menu1.add(new Services("Cuci Kering Gosok", 10000, 50, R.drawable.cuci_kering_gosok, "/kg"));
menu1.add(new Services("Jasa setrika", 8000, 50, R.drawable.jasa_setrika, "/kg"));
menu1.add(new Services("Cuci Kering Lipat", 8000, 50, R.drawable.cuci_kering_lipat, "/kg"));
menu1.add(new Services("Express Services", 16000, 50, R.drawable.expres_services, "/kg"));
ServiceMenu serviceMenu1 = new ServiceMenu("Daily kiloan", R.drawable.daily_kiloan_color, menu1);
ArrayList<Services> menu2 = new ArrayList<>();
menu2.add(new Services("Bed Cover King", 25000, 50, R.drawable.sprei, "/pc"));
menu2.add(new Services("Bed Cover Single", 20000, 50, R.drawable.sprei, "/pc"));
menu2.add(new Services("Bantal / Guling Tidur Besar", 25000, 50, R.drawable.bantal, "/pc"));
menu2.add(new Services("Bantal / Guling Tidur Sedang", 20000, 50, R.drawable.bantal, "/pc"));
menu2.add(new Services("Sarung Bantal / Guling (min 3 pc)", 5000, 50, R.drawable.sarung_bantal, "/pc"));
menu2.add(new Services("Selimut", 15000, 50, R.drawable.selimut, "/pc"));
menu2.add(new Services("Sprei / Bed Sheet", 10000, 50, R.drawable.sprei, "/pc"));
ServiceMenu serviceMenu2 = new ServiceMenu("Beddings", R.drawable.baddings_color, menu2);
ArrayList<Services> menu3 = new ArrayList<>();
menu3.add(new Services("Boneka Super Jumbo > 100 cm", 50000, 50, R.drawable.boneka_super_jumbo, "/pc"));
menu3.add(new Services("Boneka Besar > 30 cm", 25000, 50, R.drawable.boneka_besar, "/pc"));
menu3.add(new Services("Boneka Kecil < 30 cm", 15000, 50, R.drawable.boneka_kecil, "/pc"));
menu3.add(new Services("Handuk badan", 10000, 50, R.drawable.handuk_badan, "/pc"));
ServiceMenu serviceMenu3 = new ServiceMenu("Households", R.drawable.household_color, menu3);
ArrayList<Services> menu4 = new ArrayList<>();
menu4.add(new Services("Sajadah Tebal", 20000, 50, R.drawable.sajadah_tebal, "/pc"));
menu4.add(new Services("T-shirt / Kemeja Pendek (min 3 pc)", 5000, 50, R.drawable.kemeja_pendek, "/pc"));
menu4.add(new Services("T-shirt / Kemeja Panjang (min 3 pc)", 8000, 50, R.drawable.kemeja_panjang, "/pc"));
menu4.add(new Services("Celana / Rok Jeans Panjang", 12000, 50, R.drawable.celana_panjang, "/pc"));
menu4.add(new Services("Celana / Rok Jeans Pendek", 10000, 50, R.drawable.celana_pendek, "/pc"));
menu4.add(new Services("Batik Kemeja", 10000, 50, R.drawable.batik_kemeja, "/pc"));
menu4.add(new Services("Jaket / Sweater", 15000, 50, R.drawable.jaket, "/pc"));
menu4.add(new Services("Gamis Muslimah", 15000, 50, R.drawable.gamis_muslimah, "/pc"));
ServiceMenu serviceMenu4 = new ServiceMenu("Premium satuan", R.drawable.premium_color, menu4);
ArrayList<Services> menu5 = new ArrayList<>();
menu5.add(new Services("Koper besar", 45000, 50, R.drawable.koper_besar, "/pc"));
menu5.add(new Services("Ransel Besar", 20000, 50, R.drawable.ransel_besar, "/pc"));
menu5.add(new Services("Ransel Kecil", 15000, 50, R.drawable.ransel_kecil, "/pc"));
menu5.add(new Services("Sepatu (non leather)", 20000, 50, R.drawable.sepatu, "/pasang"));
ServiceMenu serviceMenu5 = new ServiceMenu("Tas & Sepatu", R.drawable.bag_shoes_color, menu5);
serviceMenuList.add(serviceMenu1);
serviceMenuList.add(serviceMenu2);
serviceMenuList.add(serviceMenu3);
serviceMenuList.add(serviceMenu4);
serviceMenuList.add(serviceMenu5);
}
private void initAdapter() {
leftAdapter = new LeftMenuAdapter(this, serviceMenuList);
rightAdapter = new RightServiceAdapter(this, serviceMenuList, servicesCart);
rightMenu.setAdapter(rightAdapter);
leftMenu.setAdapter(leftAdapter);
leftAdapter.addItemSelectedListener(this);
rightAdapter.setServicesCartImp(this);
initHeadView();
}
private void initHeadView() {
headMenu = rightAdapter.getMenuOfMenuByPosition(0);
headerLayout.setContentDescription("0");
headerView.setText(headMenu.getMenuName());
}
@Override
protected void onDestroy() {
super.onDestroy();
leftAdapter.removeItemSelectedListener(this);
}
private void showHeadView() {
headerLayout.setTranslationY(0);
View underView = rightMenu.findChildViewUnder(headerView.getX(), 0);
if (underView != null && underView.getContentDescription() != null) {
int position = Integer.parseInt(underView.getContentDescription().toString());
headMenu = rightAdapter.getMenuOfMenuByPosition(position + 1);
headerView.setText(headMenu.getMenuName());
for (int i = 0; i < serviceMenuList.size(); i++) {
if (serviceMenuList.get(i) == headMenu) {
leftAdapter.setSelectedNum(i);
break;
}
}
}
}
@Override
public void onLeftItemSelected(int position, ServiceMenu menu) {
int sum = 0;
for (int i = 0; i < position; i++) {
sum += serviceMenuList.get(i).getServicesList().size() + 1;
}
LinearLayoutManager layoutManager = (LinearLayoutManager) rightMenu.getLayoutManager();
layoutManager.scrollToPositionWithOffset(sum, 0);
leftClickType = true;
}
@Override
public void add(View view, int position) {
int[] addLocation = new int[2];
int[] cartLocation = new int[2];
int[] recycleLocation = new int[2];
view.getLocationInWindow(addLocation);
servicesCartView.getLocationInWindow(cartLocation);
rightMenu.getLocationInWindow(recycleLocation);
PointF startP = new PointF();
PointF endP = new PointF();
PointF controlP = new PointF();
startP.x = addLocation[0];
startP.y = addLocation[1] - recycleLocation[1];
endP.x = cartLocation[0];
endP.y = cartLocation[1] - recycleLocation[1];
controlP.x = endP.x;
controlP.y = startP.y;
final FakeAddImageView fakeAddImageView = new FakeAddImageView(this);
mainLayout.addView(fakeAddImageView);
fakeAddImageView.setImageResource(R.drawable.ic_add_circle_blue_700_36dp);
fakeAddImageView.getLayoutParams().width = getResources().getDimensionPixelSize(R.dimen.item_service_circle_size);
fakeAddImageView.getLayoutParams().height = getResources().getDimensionPixelSize(R.dimen.item_service_circle_size);
fakeAddImageView.setVisibility(View.VISIBLE);
ObjectAnimator addAnimator = ObjectAnimator.ofObject(fakeAddImageView, "mPointF",
new PointFTypeEvaluator(controlP), startP, endP);
addAnimator.setInterpolator(new AccelerateInterpolator());
addAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
fakeAddImageView.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animator) {
fakeAddImageView.setVisibility(View.GONE);
mainLayout.removeView(fakeAddImageView);
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
ObjectAnimator scaleAnimatorX = new ObjectAnimator().ofFloat(servicesCartView, "scaleX", 0.6f, 1.0f);
ObjectAnimator scaleAnimatorY = new ObjectAnimator().ofFloat(servicesCartView, "scaleY", 0.6f, 1.0f);
scaleAnimatorX.setInterpolator(new AccelerateInterpolator());
scaleAnimatorY.setInterpolator(new AccelerateInterpolator());
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(scaleAnimatorX).with(scaleAnimatorY).after(addAnimator);
animatorSet.setDuration(800);
animatorSet.start();
showTotalPrice();
}
@Override
public void remove(View view, int position) {
showTotalPrice();
}
@SuppressLint("SetTextI18n")
private void showTotalPrice() {
if (servicesCart != null && servicesCart.getServicesTotalPrice() > 0) {
totalPriceTextView.setVisibility(View.VISIBLE);
totalPriceTextView.setText(FormatMoney.INSTANCE.formatMoney().format((double) servicesCart.getServicesTotalPrice()));
totalPriceNumTextView.setVisibility(View.VISIBLE);
totalPriceNumTextView.setText("" + servicesCart.getServicesAccount());
} else {
totalPriceTextView.setVisibility(View.GONE);
totalPriceNumTextView.setVisibility(View.GONE);
}
}
private void showCart(View view) {
if (servicesCart != null && servicesCart.getServicesAccount() > 0) {
ServicesCartDialog dialog = new ServicesCartDialog(this, servicesCart, R.style.Cartdialog);
Window window = dialog.getWindow();
dialog.setShopCartDialogImp(this);
dialog.setCanceledOnTouchOutside(true);
dialog.setCancelable(true);
dialog.show();
WindowManager.LayoutParams params = window.getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.gravity = Gravity.BOTTOM;
params.dimAmount = 0.5f;
window.setAttributes(params);
}
}
@Override
public void dialogDismiss() {
showTotalPrice();
rightAdapter.notifyDataSetChanged();
}
}
Buat Class Transaksi ... (Still Under Development)
Setelah anda memilih jenis pakaian yang akan dilaundry, selanjutnya anda menentukan alamat dan metode pambayaran menggunakan gopay
atau cash
class TransactionActivity : AppCompatActivity() {
private var tvName: TextView? = null
private var tvAddress: TextView? = null
private var tvAddressDetail: TextView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_transaksi)
init()
}
private fun init() {
val bottomBack = findViewById<LinearLayout>(R.id.bottom_back)
bottomBack.setOnClickListener { view -> finish() }
findViewById<View>(R.id.btn_change_address).setOnClickListener { v ->
startActivity(
Intent(
this@TransactionActivity,
ChangeAddressActivity::class.java
)
)
}
val intent = intent
(findViewById<View>(R.id.services_cart_total_tv) as TextView).text =
intent.getStringExtra("total_price")
tvName = findViewById(R.id.tv_name)
tvAddress = findViewById(R.id.tv_address)
tvAddressDetail = findViewById(R.id.tv_address_detail)
if (intent.getStringExtra("address") != null) {
tvAddress!!.text = intent.getStringExtra("address")
tvAddressDetail!!.text = intent.getStringExtra("address_detail")
}
}
}
Buat Class Change Address
Digunakan untuk menentukan alamat konsumen berdasarkan pada Lokasi GPS
atau Lokasi yang dipilih pada MAP
class ChangeAddressActivity : FragmentActivity(), OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
com.google.android.gms.location.LocationListener {
private var mMap: GoogleMap? = null
private var mGoogleApiClient: GoogleApiClient? = null
private lateinit var mContext: Context
private lateinit var mAddress: TextView
private lateinit var mAddressDetail: TextView
private var mCenterLatLong: LatLng? = null
private var mBottomSheetBehavior: BottomSheetBehavior<*>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_change_address)
mContext = this
initView()
}
private fun initView() {
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment?
mAddressDetail = findViewById(R.id.tv_address_detail)
mAddress = findViewById(R.id.tv_address)
findViewById<View>(R.id.backbtn).setOnClickListener { v -> finish() }
mapFragment!!.getMapAsync(this)
if (checkPlayServices()) {
// If this check succeeds, proceed with normal processing.
// Otherwise, prompt user to get valid Play Services APK.
if (!LocationUtils.isLocationEnabled(mContext)) {
// notify userLocality
val dialog = AlertDialog.Builder(mContext)
dialog.setMessage("Location not enabled!")
dialog.setPositiveButton("Open location settings") { paramDialogInterface, paramInt ->
val myIntent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(myIntent)
}
dialog.setNegativeButton("Cancel") { paramDialogInterface, paramInt ->
// TODO Auto-generated method stub
}
dialog.show()
}
buildGoogleApiClient()
} else {
Toast.makeText(mContext, "Location not supported in this device", Toast.LENGTH_SHORT)
.show()
}
val bottomSheet = findViewById<View>(R.id.bottom_sheet)
mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
mBottomSheetBehavior!!.isHideable = true
mBottomSheetBehavior!!.state = BottomSheetBehavior.STATE_HIDDEN
findViewById<View>(R.id.btn_select_location).setOnClickListener { v ->
val intent = Intent(this@ChangeAddressActivity, TransactionActivity::class.java)
intent.putExtra("address", mAddress.text)
intent.putExtra("address_detail", mAddressDetail.text)
startActivity(intent)
}
}
override fun onMapReady(googleMap: GoogleMap) {
initialiseMap(googleMap)
}
@SuppressLint("SetTextI18n")
private fun initialiseMap(googleMap: GoogleMap) {
mMap = googleMap
Log.d(TAG, "OnMapReady")
mMap = googleMap
mMap!!.setOnCameraIdleListener {
// Cleaning all the markers.
if (mMap != null) {
mMap!!.clear()
}
mCenterLatLong = mMap!!.cameraPosition.target
mMap!!.clear()
try {
val mLocation = Location("")
mLocation.latitude = mCenterLatLong!!.latitude
mLocation.longitude = mCenterLatLong!!.longitude
getCompleteAddressString(mCenterLatLong!!.latitude, mCenterLatLong!!.longitude)
mBottomSheetBehavior!!.setState(BottomSheetBehavior.STATE_EXPANDED)
} catch (e: Exception) {
e.printStackTrace()
}
}
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return
}
}
override fun onConnected(bundle: Bundle?) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return
}
val mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient
)
if (mLastLocation != null) {
changeMap(mLastLocation)
Log.d(TAG, "ON connected")
} else
try {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this
)
} catch (e: Exception) {
e.printStackTrace()
}
try {
val mLocationRequest = LocationRequest()
mLocationRequest.interval = 10000
mLocationRequest.fastestInterval = 5000
mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this
)
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun onConnectionSuspended(i: Int) {
Log.i(TAG, "Connection suspended")
mGoogleApiClient!!.connect()
}
override fun onLocationChanged(location: Location?) {
try {
if (location != null)
changeMap(location)
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this
)
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun onConnectionFailed(connectionResult: ConnectionResult) {
}
@Synchronized
protected fun buildGoogleApiClient() {
mGoogleApiClient = GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build()
}
override fun onStart() {
super.onStart()
try {
mGoogleApiClient!!.connect()
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun onStop() {
super.onStop()
try {
} catch (e: RuntimeException) {
e.printStackTrace()
}
if (mGoogleApiClient != null && mGoogleApiClient!!.isConnected) {
mGoogleApiClient!!.disconnect()
}
}
private fun checkPlayServices(): Boolean {
val resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this)
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(
resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST
).show()
} else {
//finish();
}
return false
}
return true
}
private fun changeMap(location: Location) {
Log.d(TAG, "Reaching map" + mMap!!)
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return
}
// check if map is created successfully or not
if (mMap != null) {
mMap!!.uiSettings.isZoomControlsEnabled = false
val latLong: LatLng
latLong = LatLng(location.latitude, location.longitude)
val cameraPosition = CameraPosition.Builder()
.target(latLong).zoom(12f).build()
// .target(latLong).zoom(19f).tilt(70).build();
mMap!!.isMyLocationEnabled = true
mMap!!.uiSettings.isMyLocationButtonEnabled = true
mMap!!.animateCamera(
CameraUpdateFactory
.newCameraPosition(cameraPosition)
)
getCompleteAddressString(location.latitude, location.longitude)
} else {
Toast.makeText(
applicationContext,
"Sorry! unable to create maps", Toast.LENGTH_SHORT
)
.show()
}
}
@SuppressLint("LongLogTag")
private fun getCompleteAddressString(LATITUDE: Double, LONGITUDE: Double) {
val geocoder = Geocoder(this, Locale.getDefault())
try {
val addresses = geocoder.getFromLocation(LATITUDE, LONGITUDE, 1)
if (addresses != null) {
val returnedAddress = addresses[0]
val strReturnedAddress = StringBuilder("")
for (i in 0..returnedAddress.maxAddressLineIndex) {
strReturnedAddress.append(returnedAddress.getAddressLine(i)).append("\n")
}
mAddress.text = returnedAddress.subLocality
mAddressDetail.text = strReturnedAddress.toString()
} else {
Log.w("My Current loction address", "No Address returned!")
}
} catch (e: Exception) {
e.printStackTrace()
Log.w("My Current loction address", "Canont get Address!")
}
}
companion object {
private const val PLAY_SERVICES_RESOLUTION_REQUEST = 9000
private const val TAG = "MAP LOCATION"
}
}
Resource Template Shopping Cart Update Kodetr: Kodetr
Resource Template Shopping Cart: Github
Jika anda sudah mengikuti langkah-langkah sesuai artikel, berarti Anda sudah berhasil membuat aplikasi E-Laundry
, demikian yang dapat saya sampaikan dari artikel ini semoga bermanfaat, untuk lebih lengkapnya anda bisa lihat langkah-langkah pembuatan di bagian video, jika ada yang ditanyakan silahkan di kolom komentar dibawah, selamat mencoba.