UIComponents library provides components such as ListMenuFragment, InfoDialog, InputListFragment and NumPadDialog which will be explained below.
Building The Project
In order to use UI Components, you have to migrate your Android project to AndroidX. In Android Studio, on top menu, click on Refactor and then Migrate to AndroidX, proceed to further steps.
Download the zip file below and extract it under your project folder; MyApplication\app\libs
Changelog
Detail
Date
Added color and numpad screen for 330TR devices.
02.05.2024
Validation bug fixed when default value set on customInputFormat.
23.07.2024
Multi-conditional and multi-message added for customInputFormat.
Validate control updated fragment on first call
05.08.2024
Turkish character support added to QR.
02.09.2024
Bug fix for 1000TR menu
09.09.2024
QrScreen330 updated.
12.09.2024
Multi Currency amount support added.
28.11.2024
Lib Update: 12.09.2024
Place the uicomponents-release.aar library file into your project's "libs" folder and add it as dependency inside your app level build.gradle file like below and build your project in order to create build classes of library.
Minimum SDK version must be 25 or higher in your app level build.gradle file.
defaultConfig { minSdkVersion 25... }
App Theme
For creating all the apps identical, you have to set the colors and themes. Under your application res folder, values -> colors.xml copy and paste these resources.
Finally you have to change the theme name under your AndroidManifest.xml file.
<application ...android:theme="@style/AppTheme"> <!-- With Actionbar --><!-- OR --> android:theme="@style/AppTheme.NoActionBar"> <!-- Token theme without Actionbar --> ...</application>
After setting your theme, your activities have to look like this(empty activity);
ListMenuFragment
A fragment component which allows you to show menu items, listen menu item click events and create an automate menu tree process.
First, create your menu item class by implementing IListMenuItem interface or implement this interface from your existing data class which will be listed as menu items. Override implemented methods; getName(): Return the string that will be dislayed on menu item. getSubMenuItemList(): If a sub menu will be shown on menu item click, return list of your menu items, otherwise return null. @Nullable MenuItemClickListener getClickListener(): Each menu item's click listener seperately. @Nullable IAuthenticator getAuthenticator(): If a menu item's click event must be authorized, return an IAuthenticator object, then a pinpad screen will be shown when this menu item clicked. Authorize the password and menu item's click event will be executed. If authorization not necessary, return null for this method.
Note: Your menu items' click events will be called regardless of a sub menu will be shown or not.
You can create a class named BaseActivity and use the addFragment, replaceFragment, removeFragment and also, you can use InfoDialog's with calling from the BaseActivity.
publicabstractclassBaseActivityextendsTimeOutActivity { /** * Returns time out value in seconds for activities which extend * @see TimeOutActivity * In case of any user interaction, timeout timer will be reset. * * If any activity will not have time out, * override this method from that activity and @return '0'. */ @OverrideprotectedintgetTimeOutSec() {return60; } @OverrideprotectedvoidonCreate(@NullableBundle savedInstanceState) { super.onCreate(savedInstanceState); } @OverrideprotectedvoidonDestroy() { super.onDestroy(); }protectedvoidaddFragment(@IdResInteger resourceId,Fragment fragment,Boolean addToBackStack) {FragmentTransaction ft =getSupportFragmentManager().beginTransaction();ft.add(resourceId, fragment);if (addToBackStack) {ft.addToBackStack(""); }ft.commit(); }protectedvoidreplaceFragment(@IdResInteger resourceId,Fragment fragment,Boolean addToBackStack) {FragmentTransaction ft =getSupportFragmentManager().beginTransaction();ft.replace(resourceId, fragment);if (addToBackStack) {ft.addToBackStack(""); }ft.commit(); }protectedvoidremoveFragment(Fragment fragment) {FragmentTransaction ft =getSupportFragmentManager().beginTransaction();ft.remove(fragment);ft.commit(); }}
In your MainActivity (or another Activity class) you can list the menu items like this;
With help of clicking to a menu item you can update the fragment and create a sub menu with sub menu items. Under the prepareData() which we created previously, you have to add another list of sub menu items.
publicvoidprepareData() {List<IListMenuItem> subList1 =newArrayList<>(); // Creating a list for your sub menu items/* Your Sub List Items*/subList1.add(newMenuItem("MenuItem 1", (menuItem) -> {Toast.makeText(this,"Sub Menu 1",Toast.LENGTH_LONG).show(); },null));subList1.add(newMenuItem("MenuItem 2", (menuItem) -> {Toast.makeText(this,"Sub Menu 2",Toast.LENGTH_LONG).show(); },null));subList1.add(newMenuItem("MenuItem 3", (menuItem) -> {Toast.makeText(this,"Sub Menu 3",Toast.LENGTH_LONG).show(); },null));menuItems.add(newMenuItem("Sub Menu", subList1,null)); // The menu item in to the List Menu Fragment}
ConfirmationDialog
At the previous example; we created a BaseActivity and implemented it from MainActivity, you can add your Confirmation Dialog methods to there.
/** * Shows a dialog to the user which asks for a confirmation. * Dialog will be dismissed automatically when user taps on to confirm/cancel button. * See {@link InfoDialog#newInstance(InfoDialog.InfoType, String, String, InfoDialog.InfoDialogButtons, int, InfoDialogListener)}
*/ protected InfoDialog showConfirmationDialog(InfoDialog.InfoType type, String title, String info, InfoDialog.InfoDialogButtons buttons, int arg, InfoDialogListener listener) {
InfoDialog dialog =InfoDialog.newInstance(type, title, info, buttons, arg, listener);dialog.show(getSupportFragmentManager(),"");return dialog; }
Confirmation Dialog can have various information types. The base code to call a Confirmation Dialog is;
For this example we have a warning info type. After the InfoType. you can add Uploading, QR, Progress, Processing, None, Info, Error, Downloading, Declined, Connecting, Confirmed. Also, you can cahnge the confirmation type.
After the InfoDialog.InfoDialogButtons. you can add Both, Confirm, Cancel for restricting the buttons.
Implementing the confirm and cancel actions.
@Overridepublicvoidconfirmed(int arg) {if (arg ==99) {// Do something else... }//else if (arg == ***) { Do something else... } } @Overridepublicvoidcanceled(int arg) {if (arg ==99) {// Do something else... }//else if (arg == ***) { Do something else... } }
InfoDialog
InfoDialog component to show the user information about the process.
InfoDialog's have same Dialog types Uploading, QR, Progress, Processing, None, Info, Error, Downloading, Declined, Connecting, Confirmed and has a isCancelable selection true or false.
Usage is like below(you can place the code in the BaseActivity.java):
/** * Shows a dialog to the user which informs the user about current progress. * See {@linkInfoDialog#newInstance(InfoDialog.InfoType, String, boolean)} * Dialog can dismissed by calling .dismiss() method of the fragment instance returned from this method. */protectedInfoDialogshowInfoDialog(InfoDialog.InfoType type,String text,boolean isCancelable) {InfoDialog fragment =InfoDialog.newInstance(type, text, isCancelable);fragment.show(getSupportFragmentManager(),"");return fragment; } /** * Shows a dialog to the user which asks for a confirmation. * Dialog will be dismissed automatically when user taps on to confirm/cancel button. * See {@link InfoDialog#newInstance(InfoDialog.InfoType, String, String, InfoDialog.InfoDialogButtons, int, InfoDialogListener)}
*/ protected InfoDialog showConfirmationDialog(InfoDialog.InfoType type, String title, String info, InfoDialog.InfoDialogButtons buttons, int arg, InfoDialogListener listener) {
InfoDialog dialog =InfoDialog.newInstance(type, title, info, buttons, arg, listener);dialog.show(getSupportFragmentManager(),"");return dialog; }
Add the QR Payment object to the ReadCard Method, detailed explanation; Card Service
obj.put("qrPay",1);
Sample QR Request Method
protectedvoidQrSale() {InfoDialog dialog =showInfoDialog(InfoDialog.InfoType.Progress,"Please Wait",true);// Request to Show a QR Code -> cardServiceBinding.showQR("PLEASE READ THE QR CODE", StringHelper.getAmount(amount), qrString); // Shows QR on the back screen
dialog.setQr(qrString,"Waiting For The QR Code To Read"); // Shows the same QR on Info Dialog// Request a QR Response ->/* * Your QR Response */dialog.setDismissedListener(() -> { // This method listens for the dismiss of the QR Dialog// You can call your QR Payment Cancel method here }); }
InputListFragment
You can create an input list by creating a CustomInputFormat list and setting it to an InputListFragment.
/** * * @param hint: Title to be shown above edittext. * @param type: Input format for edittext. * @param maxLength: Maximum length for input string. If null, maximum length will not be set. * @param invalidMessage: Warning message to be shown under edit text in case input is not valid. * @param validator: An object that is a type of InputValidator. Required if related input must be validated. * If validator is null, input will always be valid no matter if it's empty or not. */publicCustomInputFormat(String hint,EditTextInputType type, @NullableInteger maxLength, @NullableString invalidMessage, @NullableInputValidator validator)
Create your CustomInputFormat list like below:
List<CustomInputFormat> inputList =newArrayList<>(); inputList.add(new CustomInputFormat("Card Number", EditTextInputType.CreditCardNumber, null, "Invalid card number!", validator));
inputList.add(newCustomInputFormat("Expire Date",EditTextInputType.ExpiryDate,null,null,null));inputList.add(newCustomInputFormat("CVV",EditTextInputType.CVV,null,null,null)); inputList.add(new CustomInputFormat("Amount", EditTextInputType.AmountDot, null, null, null)); // For 1000TR Keyboard, amount input will be 1,00 for 1TL. text.replace(",", "") for 100.
You can set default text to inputs by setting text to CustomInputFormat
If you want special validator for multi conditional input you can use example code block.
This code block allows instant multi-conditional and message serving for the validator:
InputValidator tempValidator =newInputValidator() { @Overridepublicbooleanvalidate(CustomInputFormat customInputFormat) {if(customInputFormat.getText().length() ==2){customInputFormat.setInvalidMessage("INPUT LEN SHOULD NOT BE 2");returncustomInputFormat.getText().length() ==6; }elseif(customInputFormat.getText().length() ==3){customInputFormat.setInvalidMessage("INPUT LEN SHOULD NOT BE 3");returncustomInputFormat.getText().length() ==6; }else{customInputFormat.setInvalidMessage(getString(R.string.auth_code_invalid_six_digit));returncustomInputFormat.getText().length() ==6; } } }; inputAuthCode = new CustomInputFormat(getString(R.string.return_auth_code), EditTextInputType.Text, 6, getString(R.string.auth_code_invalid_six_digit),
tempValidator);inputList.add(inputAuthCode);
Pass your CustomInputFormat list to InputListFragment constructor method and add your fragment:
InputListFragment fragment =InputListFragment.newInstance(inputList);addFragment(R.id.container, fragment,true);//addFragment method should be like:protectedvoidaddFragment(@IdResInteger resourceId,Fragment fragment,Boolean addToBackStack) {FragmentTransaction ft =getSupportFragmentManager().beginTransaction();ft.add(resourceId, fragment);if (addToBackStack) {ft.addToBackStack(""); }ft.commit(); }
You can check if all fields are valid or not by calling isValid() method of fragment:
Boolean inputsValid =fragment.isValid();
If any of the fields has an invalid input, isValid() method will return "false", if all field inputs are valid, it will return "true".
After validating the inputs, you can get the input list by calling getInputList() method which will return list of input strings in order:
List<String> inputList =fragment.getInputList();
If you activate the Input list fragment on another fragment or activity and want to return to the previous activity, you have to set the addToBackStackfalse;
addFragment(R.id.container, fragment,false);
NumPadDialog
Numeric PIN input dialog which is shown automatically if a ListMenu item has authenticator, or you can use it independently like below:
NumPadDialog dialog =NumPadDialog.newInstance(newNumPadListener() { @Overridepublicvoidenter(String pin) {//Pin entry callback } @OverridepublicvoidonCanceled() {//Numpad canceled callback } },"Please enter PIN",8); /* Maximum pin length:8, change the integer 8 for the length you want */dialog.show(getSupportFragmentManager(),"numpad");
Adding Visual Details to Your App
Your app theme has a harmony but also UIComponents Library gives you permission to customize your app in a limit. You can add your logo and titles to the fragments of your app, you can use backButton's or Android navigation buttons.
Add your my_logo.png file under the res -> drawable folder and call as R.drawable.my_logo.png
Under your Activity.java file, inside the onCreate method you have to create a fragment.
ListMenuFragment fragment = ListMenuFragment.newInstance(menuItems, "POS Operations", false, R.drawable.token_logo); //false for no back button
addFragment(R.id.container, fragment,false);
InputListFragment fragment =InputListFragment.newInstance(inputList); addFragment(R.id.container, fragment, false); // If you want to go back to the previous activity; set addToBackStack false
fragment.setActionLayout("Input List",true,R.drawable.token_logo); // true for hasBackButton