372 lines
12 KiB
Java
372 lines
12 KiB
Java
package com.example.bdkipoc;
|
|
|
|
import android.animation.AnimatorSet;
|
|
import android.animation.ObjectAnimator;
|
|
import android.content.Intent;
|
|
import android.graphics.Color;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
import android.text.TextUtils;
|
|
import android.view.View;
|
|
import android.view.Window;
|
|
import android.view.WindowManager;
|
|
import android.view.animation.AccelerateDecelerateInterpolator;
|
|
import android.widget.Button;
|
|
import android.widget.EditText;
|
|
import android.widget.ImageView;
|
|
import android.widget.LinearLayout;
|
|
import android.widget.TextView;
|
|
import android.widget.Toast;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
public class PaymentActivity extends AppCompatActivity {
|
|
|
|
// Views
|
|
private EditText editTextAmount;
|
|
private Button confirmButton;
|
|
private LinearLayout backNavigation;
|
|
private ImageView backArrow;
|
|
private TextView toolbarTitle;
|
|
|
|
// Numpad buttons
|
|
private TextView btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8, btn9, btn0, btn000;
|
|
private ImageView btnDelete;
|
|
|
|
// Data
|
|
private StringBuilder currentAmount = new StringBuilder();
|
|
private static final int MAX_AMOUNT_LENGTH = 12;
|
|
|
|
// Animation
|
|
private Handler animationHandler = new Handler(Looper.getMainLooper());
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
|
|
// Set status bar color programmatically
|
|
setStatusBarColor();
|
|
|
|
setContentView(R.layout.activity_payment);
|
|
|
|
initializeViews();
|
|
setupClickListeners();
|
|
setupInitialStates();
|
|
// REMOVED: addAnimations() - No more card sliding animation
|
|
}
|
|
|
|
private void setStatusBarColor() {
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
Window window = getWindow();
|
|
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
|
window.setStatusBarColor(Color.parseColor("#E31937")); // Red color
|
|
|
|
// Make status bar icons white (for dark red background)
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
View decorView = window.getDecorView();
|
|
decorView.setSystemUiVisibility(0); // Clear light status bar flag
|
|
}
|
|
}
|
|
}
|
|
|
|
private void initializeViews() {
|
|
// Main views
|
|
editTextAmount = findViewById(R.id.editTextAmount);
|
|
confirmButton = findViewById(R.id.confirmButton);
|
|
backNavigation = findViewById(R.id.back_navigation);
|
|
backArrow = findViewById(R.id.backArrow);
|
|
toolbarTitle = findViewById(R.id.toolbarTitle);
|
|
|
|
// Numpad buttons
|
|
btn1 = findViewById(R.id.btn1);
|
|
btn2 = findViewById(R.id.btn2);
|
|
btn3 = findViewById(R.id.btn3);
|
|
btn4 = findViewById(R.id.btn4);
|
|
btn5 = findViewById(R.id.btn5);
|
|
btn6 = findViewById(R.id.btn6);
|
|
btn7 = findViewById(R.id.btn7);
|
|
btn8 = findViewById(R.id.btn8);
|
|
btn9 = findViewById(R.id.btn9);
|
|
btn0 = findViewById(R.id.btn0);
|
|
btn000 = findViewById(R.id.btn000);
|
|
btnDelete = findViewById(R.id.btnDelete);
|
|
}
|
|
|
|
private void setupClickListeners() {
|
|
// Back navigation - entire LinearLayout is clickable
|
|
backNavigation.setOnClickListener(v -> {
|
|
addClickAnimation(v);
|
|
navigateBack();
|
|
});
|
|
|
|
// Individual back arrow (for additional touch area)
|
|
backArrow.setOnClickListener(v -> {
|
|
addClickAnimation(v);
|
|
navigateBack();
|
|
});
|
|
|
|
// Toolbar title (also clickable for back navigation)
|
|
toolbarTitle.setOnClickListener(v -> {
|
|
addClickAnimation(v);
|
|
navigateBack();
|
|
});
|
|
|
|
// Numpad listeners
|
|
btn1.setOnClickListener(v -> handleNumpadClick(v, "1"));
|
|
btn2.setOnClickListener(v -> handleNumpadClick(v, "2"));
|
|
btn3.setOnClickListener(v -> handleNumpadClick(v, "3"));
|
|
btn4.setOnClickListener(v -> handleNumpadClick(v, "4"));
|
|
btn5.setOnClickListener(v -> handleNumpadClick(v, "5"));
|
|
btn6.setOnClickListener(v -> handleNumpadClick(v, "6"));
|
|
btn7.setOnClickListener(v -> handleNumpadClick(v, "7"));
|
|
btn8.setOnClickListener(v -> handleNumpadClick(v, "8"));
|
|
btn9.setOnClickListener(v -> handleNumpadClick(v, "9"));
|
|
btn0.setOnClickListener(v -> handleNumpadClick(v, "0"));
|
|
btn000.setOnClickListener(v -> handleNumpadClick(v, "000"));
|
|
|
|
// Delete button
|
|
btnDelete.setOnClickListener(v -> {
|
|
addClickAnimation(v);
|
|
deleteLastDigit();
|
|
});
|
|
|
|
// Confirm button
|
|
confirmButton.setOnClickListener(v -> {
|
|
if (confirmButton.isEnabled()) {
|
|
addButtonClickAnimation(v);
|
|
handleConfirmPayment();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void navigateBack() {
|
|
// Simple back navigation without card animation
|
|
finish();
|
|
}
|
|
|
|
private void handleNumpadClick(View view, String digit) {
|
|
addClickAnimation(view);
|
|
addDigit(digit);
|
|
}
|
|
|
|
private void setupInitialStates() {
|
|
// Set initial amount display
|
|
editTextAmount.setText("");
|
|
|
|
// Set initial button state
|
|
updateButtonState();
|
|
|
|
// Disable EditText input (only numpad input allowed)
|
|
editTextAmount.setFocusable(false);
|
|
editTextAmount.setClickable(false);
|
|
editTextAmount.setCursorVisible(false);
|
|
}
|
|
|
|
// REMOVED: addAnimations() method - No card sliding animation on startup
|
|
|
|
private void addDigit(String digit) {
|
|
// Validate input length
|
|
if (currentAmount.length() >= MAX_AMOUNT_LENGTH) {
|
|
showToast("Maksimal " + MAX_AMOUNT_LENGTH + " digit");
|
|
return;
|
|
}
|
|
|
|
// Handle leading zeros
|
|
if (currentAmount.length() == 0) {
|
|
if (digit.equals("000")) {
|
|
// Don't allow 000 as first input
|
|
return;
|
|
}
|
|
currentAmount.append(digit);
|
|
} else if (currentAmount.length() == 1 && currentAmount.toString().equals("0")) {
|
|
if (!digit.equals("000")) {
|
|
// Replace single 0 with new digit
|
|
currentAmount = new StringBuilder(digit);
|
|
} else {
|
|
return;
|
|
}
|
|
} else {
|
|
currentAmount.append(digit);
|
|
}
|
|
|
|
updateAmountDisplay();
|
|
updateButtonState();
|
|
addInputFeedback();
|
|
}
|
|
|
|
private void deleteLastDigit() {
|
|
if (currentAmount.length() > 0) {
|
|
String current = currentAmount.toString();
|
|
|
|
// If current ends with 000, remove all three digits
|
|
if (current.endsWith("000") && current.length() >= 3) {
|
|
currentAmount.delete(currentAmount.length() - 3, currentAmount.length());
|
|
} else {
|
|
currentAmount.deleteCharAt(currentAmount.length() - 1);
|
|
}
|
|
|
|
updateAmountDisplay();
|
|
updateButtonState();
|
|
addDeleteFeedback();
|
|
}
|
|
}
|
|
|
|
private void updateAmountDisplay() {
|
|
String amount = currentAmount.toString();
|
|
|
|
if (amount.isEmpty() || amount.equals("0")) {
|
|
editTextAmount.setText("");
|
|
} else {
|
|
String formattedAmount = formatCurrency(amount);
|
|
editTextAmount.setText(formattedAmount);
|
|
}
|
|
}
|
|
|
|
private String formatCurrency(String amount) {
|
|
if (TextUtils.isEmpty(amount) || amount.equals("0")) {
|
|
return "";
|
|
}
|
|
|
|
try {
|
|
long number = Long.parseLong(amount);
|
|
return String.format("%,d", number).replace(',', '.');
|
|
} catch (NumberFormatException e) {
|
|
return amount;
|
|
}
|
|
}
|
|
|
|
private void updateButtonState() {
|
|
boolean hasValidAmount = currentAmount.length() > 0 &&
|
|
!currentAmount.toString().equals("0") &&
|
|
!currentAmount.toString().isEmpty();
|
|
|
|
confirmButton.setEnabled(hasValidAmount);
|
|
|
|
if (hasValidAmount) {
|
|
// Active state
|
|
confirmButton.setBackgroundResource(R.drawable.button_active_background);
|
|
confirmButton.setTextColor(Color.WHITE);
|
|
confirmButton.setAlpha(1.0f);
|
|
} else {
|
|
// Inactive state
|
|
confirmButton.setBackgroundResource(R.drawable.button_inactive_background);
|
|
confirmButton.setTextColor(Color.parseColor("#999999"));
|
|
confirmButton.setAlpha(0.6f);
|
|
}
|
|
}
|
|
|
|
private void handleConfirmPayment() {
|
|
String amount = currentAmount.toString();
|
|
|
|
if (TextUtils.isEmpty(amount) || amount.equals("0")) {
|
|
showToast("Masukkan jumlah pembayaran");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
long amountValue = Long.parseLong(amount);
|
|
|
|
// Validate minimum amount
|
|
if (amountValue < 1000) {
|
|
showToast("Minimal pembayaran Rp 1.000");
|
|
return;
|
|
}
|
|
|
|
// Validate maximum amount
|
|
if (amountValue > 999999999L) {
|
|
showToast("Maksimal pembayaran Rp 999.999.999");
|
|
return;
|
|
}
|
|
|
|
// Process payment
|
|
processPayment(amountValue);
|
|
|
|
} catch (NumberFormatException e) {
|
|
showToast("Format jumlah tidak valid");
|
|
}
|
|
}
|
|
|
|
private void processPayment(long amount) {
|
|
// Show loading state
|
|
confirmButton.setText("Memproses...");
|
|
confirmButton.setEnabled(false);
|
|
|
|
// Simulate payment processing
|
|
animationHandler.postDelayed(() -> {
|
|
// Show success message
|
|
showToast("Pembayaran berhasil! Jumlah: Rp " + formatCurrency(String.valueOf(amount)));
|
|
|
|
// Reset state and go back
|
|
resetPaymentState();
|
|
navigateBack();
|
|
}, 2000);
|
|
}
|
|
|
|
private void resetPaymentState() {
|
|
currentAmount = new StringBuilder();
|
|
updateAmountDisplay();
|
|
updateButtonState();
|
|
confirmButton.setText("Konfirmasi");
|
|
}
|
|
|
|
// Animation methods (only for numpad interactions)
|
|
private void addClickAnimation(View view) {
|
|
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.95f, 1f);
|
|
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.95f, 1f);
|
|
|
|
AnimatorSet animatorSet = new AnimatorSet();
|
|
animatorSet.playTogether(scaleX, scaleY);
|
|
animatorSet.setDuration(150);
|
|
animatorSet.start();
|
|
}
|
|
|
|
private void addButtonClickAnimation(View view) {
|
|
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.98f, 1f);
|
|
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.98f, 1f);
|
|
|
|
AnimatorSet animatorSet = new AnimatorSet();
|
|
animatorSet.playTogether(scaleX, scaleY);
|
|
animatorSet.setDuration(200);
|
|
animatorSet.start();
|
|
}
|
|
|
|
private void addInputFeedback() {
|
|
ObjectAnimator fadeIn = ObjectAnimator.ofFloat(editTextAmount, "alpha", 0.7f, 1f);
|
|
fadeIn.setDuration(200);
|
|
fadeIn.start();
|
|
}
|
|
|
|
private void addDeleteFeedback() {
|
|
ObjectAnimator shake = ObjectAnimator.ofFloat(editTextAmount, "translationX", 0f, -10f, 10f, 0f);
|
|
shake.setDuration(300);
|
|
shake.start();
|
|
}
|
|
|
|
// Utility methods
|
|
private void showToast(String message) {
|
|
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
|
}
|
|
|
|
@Override
|
|
public void onBackPressed() {
|
|
navigateBack();
|
|
}
|
|
|
|
@Override
|
|
protected void onDestroy() {
|
|
super.onDestroy();
|
|
if (animationHandler != null) {
|
|
animationHandler.removeCallbacksAndMessages(null);
|
|
}
|
|
}
|
|
|
|
// Public methods for testing
|
|
public String getCurrentAmount() {
|
|
return currentAmount.toString();
|
|
}
|
|
|
|
public boolean isConfirmButtonEnabled() {
|
|
return confirmButton.isEnabled();
|
|
}
|
|
} |