add project adins

This commit is contained in:
Alfrid Sanjaya Leo Putra 2024-07-25 14:44:22 +07:00
commit f8f85d679d
5299 changed files with 625430 additions and 0 deletions

View file

@ -0,0 +1,418 @@
package com.adins.mss.base.dynamicform.form;
import android.Manifest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import androidx.annotation.Keep;
import androidx.fragment.app.FragmentManager;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import com.adins.mss.base.GlobalData;
import com.adins.mss.base.NewMainActivity;
import com.adins.mss.base.R;
import com.adins.mss.base.commons.AppInfo;
import com.adins.mss.base.commons.Helper;
import com.adins.mss.base.crashlytics.FireCrash;
import com.adins.mss.base.dynamicform.Constant;
import com.adins.mss.base.dynamicform.CustomerFragment;
import com.adins.mss.base.dynamicform.DynamicFormActivity;
import com.adins.mss.base.dynamicform.SurveyHeaderBean;
import com.adins.mss.base.dynamicform.form.view.DynamicQuestionView;
import com.adins.mss.base.payment.PaxPayment;
import com.adins.mss.base.util.EventBusHelper;
import com.adins.mss.base.util.LocaleHelper;
import com.adins.mss.base.util.Utility;
import com.adins.mss.constant.Global;
import com.adins.mss.foundation.UserHelp.Bean.UserHelpView;
import com.adins.mss.foundation.UserHelp.UserHelp;
import com.adins.mss.foundation.dialog.DialogManager;
import com.adins.mss.foundation.image.Utils;
import com.adins.mss.foundation.location.UpdateMenuIcon;
import com.adins.mss.foundation.security.storepreferences.ObscuredSharedPreferences;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.google.firebase.perf.FirebasePerformance;
import com.google.firebase.perf.metrics.Trace;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.acra.ACRA;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Map;
import static com.adins.mss.constant.Global.SHOW_USERHELP_DELAY_DEFAULT;
public class DynamicQuestionActivity extends AppCompatActivity implements LocationListener,
AdapterView.OnItemClickListener, AppInfo {
public static FragmentManager fragmentManager;
public static ProgressDialog progressDialog;
protected static ArrayList<String> questionLabel = new ArrayList<>();
LocationManager mLocation = null;
private DynamicQuestionView view;
private Trace detailTrace;
private FirebaseAnalytics screenName;
public static ArrayList<String> getQuestionLabel() {
return questionLabel;
}
public static void setQuestionLabel(ArrayList<String> questionLabel) {
DynamicQuestionActivity.questionLabel = questionLabel;
}
@Override
public void onResume() {
super.onResume();
//Firebase Custom Trace
detailTrace.start();
screenName.setCurrentScreen(this, getString(R.string.screen_name_customer_detail),null);
if (Global.getSharedGlobal().getIsVerifiedByUser()) {
Global.getSharedGlobal().setIsVerifiedByUser(false);
this.finish();
}
DialogManager.showGPSAlert(DynamicQuestionActivity.this);
DialogManager.showTimeProviderAlert(this);
if ((Helper.isDevEnabled(this) && GlobalData.getSharedGlobalData().isDevEnabled()) && !GlobalData.getSharedGlobalData().isByPassDeveloper()) {
DialogManager.showTurnOffDevMode(this);
}
registerReceiver(paymentResultReceiver, new IntentFilter("com.broadcast.BNI_APP"));
}
@Override
protected void onPause() {
super.onPause();
//Firebase Custom Trace
detailTrace.stop();
unregisterReceiver(paymentResultReceiver);
}
@Keep // subcribe
public void onEvent(SurveyHeaderBean task) {
Global.getSharedGlobal().setIsVerifiedByUser(false);
this.finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
Utility.freeMemory();
Constant.setListOfQuestion(null);
CustomerFragment.setHeader(null);
DynamicFormActivity.setListOfIdentifier(null);
DynamicFormActivity.setIsApproval(false);
DynamicFormActivity.setIsVerified(false);
DynamicFormActivity.setAllowImageEdit(true);
DynamicQuestionView.fragmentManager = null;
fragmentManager = null;
if (mLocation != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
} else {
mLocation.removeUpdates(this);
mLocation = null;
}
} else {
mLocation.removeUpdates(this);
mLocation = null;
}
}
EventBusHelper.unregisterEventBus(this);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Firebase custom trace
detailTrace = FirebasePerformance.getInstance().newTrace(getString(R.string.customer_detail_trace));
screenName = FirebaseAnalytics.getInstance(this);
EventBusHelper.registerEventBus(this);
setContentView(R.layout.activity_dynamic_question);
fragmentManager = getSupportFragmentManager();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitleTextColor(getResources().getColor(R.color.fontColorWhite));
setSupportActionBar(toolbar);
view = new DynamicQuestionView(this);
view.fragmentManager = fragmentManager;
view.onCreate();
ACRA.getErrorReporter().putCustomData("LAST_CLASS_ACCESSED", getClass().getSimpleName());
LinearLayout btnContainer = findViewById(R.id.buttonContainer);
btnContainer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if(!UserHelp.isActive) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
UserHelp.showAllUserHelp(DynamicQuestionActivity.this, DynamicQuestionActivity.this.getClass().getSimpleName());
}
}, SHOW_USERHELP_DELAY_DEFAULT);
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(com.adins.mss.base.R.menu.main_menu, menu);
mainMenu = menu;
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
updateMenuIcon();
if(Global.ENABLE_USER_HELP &&
(Global.userHelpGuide.get(DynamicQuestionActivity.class.getSimpleName())!=null) ||
Global.userHelpDummyGuide.get(DynamicQuestionActivity.class.getSimpleName()) != null){
menu.findItem(R.id.mnGuide).setVisible(true);
}
return super.onPrepareOptionsMenu(menu);
}
private static Menu mainMenu;
public static void updateMenuIcon() {
UpdateMenuIcon uItem = new UpdateMenuIcon();
uItem.updateGPSIcon(mainMenu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.mnGuide && !Global.BACKPRESS_RESTRICTION){
LinearLayout btnContainer = findViewById(R.id.buttonContainer);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
UserHelp.showAllUserHelp(DynamicQuestionActivity.this, DynamicQuestionActivity.this.getClass().getSimpleName());
}
}, SHOW_USERHELP_DELAY_DEFAULT);
btnContainer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (!UserHelp.isActive)
UserHelp.showAllUserHelp(DynamicQuestionActivity.this, DynamicQuestionActivity.this.getClass().getSimpleName());
}
});
String activityName = this.getClass().getSimpleName();
ObscuredSharedPreferences sharedPref =
ObscuredSharedPreferences.getPrefs(getApplicationContext(), "GlobalData", Context.MODE_PRIVATE);
String tooltipString = sharedPref.getString("TOOLTIP", null);
Gson gson = new Gson();
Map<String, ArrayList<UserHelpView>> tempTooltip;
java.lang.reflect.Type type = new TypeToken<Map<String, ArrayList<UserHelpView>>>() {
}.getType();
tempTooltip = gson.fromJson(tooltipString, type);
Global.userHelpGuide.put(activityName, tempTooltip.get(activityName));
}
return super.onOptionsItemSelected(item);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//
}
@Override
public void onBackPressed() {
if(!Global.BACKPRESS_RESTRICTION) {
if (view.mode == Global.MODE_VIEW_SENT_SURVEY) {
super.onBackPressed();
GlobalData.getSharedGlobalData().setDoingTask(false);
} else {
DialogManager.showExitAlertQuestion(this, getString(R.string.alertExitSurvey));
}
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == Global.REQUEST_DRAWING_QUESTION) {
Bundle bundle = data.getExtras();
bundle.putInt(FragmentQuestion.BUND_KEY_ACTION, FragmentQuestion.RESULT_FROM_DRAWING_QUESTION);
Message message = new Message();
message.setData(bundle);
FragmentQuestion.questionHandler.sendMessage(message);
} else if (requestCode == Utils.REQUEST_IN_APP_CAMERA) {
Bundle bundle = data.getExtras();
if (bundle != null) {
bundle.putInt(FragmentQuestion.BUND_KEY_ACTION, FragmentQuestion.RESULT_FROM_BUILT_IN_CAMERA);
Message message = new Message();
message.setData(bundle);
FragmentQuestion.questionHandler.sendMessage(message);
}
} else if (requestCode == Utils.REQUEST_CAMERA) {
Bundle bundle = data.getExtras();
if (bundle != null) {
bundle.putInt(FragmentQuestion.BUND_KEY_ACTION, FragmentQuestion.RESULT_FROM_ANDROID_CAMERA);
Message message = new Message();
message.setData(bundle);
FragmentQuestion.questionHandler.sendMessage(message);
}
} else if (requestCode == Global.REQUEST_LOCATIONTAGGING) {
Bundle bundle = new Bundle();
bundle.putInt(FragmentQuestion.BUND_KEY_ACTION, FragmentQuestion.RESULT_FROM_LOCATION_QUESTION);
Message message = new Message();
message.setData(bundle);
FragmentQuestion.questionHandler.sendMessage(message);
} else if (requestCode == Global.REQUEST_VOICE_NOTES) {
byte[] voiceNotes = data.getByteArrayExtra(Global.BUND_KEY_DETAIL_DATA);
if (voiceNotes != null && voiceNotes.length > 0) {
view.header.setVoice_note(voiceNotes);
}
} else if (requestCode == Global.REQUEST_EDIT_IMAGE) {
Bundle bundle = data.getExtras();
if (bundle != null) {
bundle.putInt(FragmentQuestion.BUND_KEY_ACTION, FragmentQuestion.RESULT_FROM_EDIT_IMAGE);
Message message = new Message();
message.setData(bundle);
FragmentQuestion.questionHandler.sendMessage(message);
}
} else if (requestCode == Global.REQUEST_LOOKUP_ANSWER) {
Bundle bundle = data.getExtras();
if (bundle != null) {
bundle.putInt(FragmentQuestion.BUND_KEY_ACTION, FragmentQuestion.RESULT_FROM_LOOKUP_CRITERIA);
Message message = new Message();
message.setData(bundle);
FragmentQuestion.questionHandler.sendMessage(message);
}
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case Utility.REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS:
if (Utility.checkPermissionResult(this, permissions, grantResults))
bindLocationListener();
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private void bindLocationListener() {
mLocation = (LocationManager) getSystemService(LOCATION_SERVICE);
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Utility.checkPermissionGranted(this);
return;
} else {
if (mLocation.getAllProviders().contains(LocationManager.GPS_PROVIDER))
mLocation.requestSingleUpdate(LocationManager.GPS_PROVIDER, this, null);
}
} else {
if (mLocation.getAllProviders().contains(LocationManager.GPS_PROVIDER))
mLocation.requestSingleUpdate(LocationManager.GPS_PROVIDER, this, null);
}
} catch (Exception e) {
FireCrash.log(e);
}
}
@Override
protected void attachBaseContext(Context newBase) {
Context context = newBase;
Locale locale;
try{
locale = new Locale(GlobalData.getSharedGlobalData().getLocale());
context = LocaleHelper.wrap(newBase, locale);
} catch (Exception e) {
locale = new Locale(LocaleHelper.ENGLSIH);
context = LocaleHelper.wrap(newBase, locale);
} finally {
super.attachBaseContext(context);
}
}
@Override
public void onLocationChanged(Location location) {
if (location != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && location.isFromMockProvider()) {
DialogManager.showMockDialog(this);
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
//EMPTY
}
@Override
public void onProviderEnabled(String provider) {
DialogManager.closeGPSAlert();
}
@Override
public void onProviderDisabled(String provider) {
DialogManager.showGPSAlert(DynamicQuestionActivity.this);
}
@Override
public void checkAppVersion(NewMainActivity activity) {
//EMPTY
}
private BroadcastReceiver paymentResultReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
assert action != null;
if (action.equalsIgnoreCase(PaxPayment.ACTION_SUCCESS_PAYMENT)) {
String result = intent.getStringExtra("Result");
if (result.toUpperCase().contains("SALE")) {
Bundle bundle = new Bundle();
bundle.putInt(FragmentQuestion.BUND_KEY_ACTION, FragmentQuestion.SUBMIT_FORM);
Message message = new Message();
message.setData(bundle);
FragmentQuestion.questionHandler.sendMessage(message);
}
}
}
};
}

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="10dp" />
<solid android:color="@color/fontColorWhite" />
<stroke android:color="@color/gradient_end"
android:width="3dp"/>
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -0,0 +1,348 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.adins.libs.nineoldandroids.view;
import android.os.Build;
import android.view.View;
import android.view.animation.Interpolator;
import com.adins.libs.nineoldandroids.animation.Animator;
import java.util.WeakHashMap;
/**
* This class enables automatic and optimized animation of select properties on View objects.
* If only one or two properties on a View object are being animated, then using an
* {@link android.animation.ObjectAnimator} is fine; the property setters called by ObjectAnimator
* are well equipped to do the right thing to set the property and invalidate the view
* appropriately. But if several properties are animated simultaneously, or if you just want a
* more convenient syntax to animate a specific property, then ViewPropertyAnimator might be
* more well-suited to the task.
* <p>
* <p>This class may provide better performance for several simultaneous animations, because
* it will optimize invalidate calls to take place only once for several properties instead of each
* animated property independently causing its own invalidation. Also, the syntax of using this
* class could be easier to use because the caller need only tell the View object which
* property to animate, and the value to animate either to or by, and this class handles the
* details of configuring the underlying Animator class and starting it.</p>
* <p>
* <p>This class is not constructed by the caller, but rather by the View whose properties
* it will animate. Calls to {@link android.view.View#animate()} will return a reference
* to the appropriate ViewPropertyAnimator object for that View.</p>
*/
public abstract class ViewPropertyAnimator {
private static final WeakHashMap<View, ViewPropertyAnimator> ANIMATORS =
new WeakHashMap<View, ViewPropertyAnimator>(0);
/**
* This method returns a ViewPropertyAnimator object, which can be used to animate specific
* properties on this View.
*
* @param view View to animate.
* @return The ViewPropertyAnimator associated with this View.
*/
public static ViewPropertyAnimator animate(View view) {
ViewPropertyAnimator animator = ANIMATORS.get(view);
if (animator == null) {
final int version = Build.VERSION.SDK_INT;
if (version >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
animator = new ViewPropertyAnimatorICS(view);
} else if (version >= Build.VERSION_CODES.HONEYCOMB) {
animator = new ViewPropertyAnimatorHC(view);
} else {
animator = new ViewPropertyAnimatorPreHC(view);
}
ANIMATORS.put(view, animator);
}
return animator;
}
/**
* Returns the current duration of property animations. If the duration was set on this
* object, that value is returned. Otherwise, the default value of the underlying Animator
* is returned.
*
* @return The duration of animations, in milliseconds.
* @see #setDuration(long)
*/
public abstract long getDuration();
/**
* Sets the duration for the underlying animator that animates the requested properties.
* By default, the animator uses the default value for ValueAnimator. Calling this method
* will cause the declared value to be used instead.
*
* @param duration The length of ensuing property animations, in milliseconds. The value
* cannot be negative.
* @return This object, allowing calls to methods in this class to be chained.
*/
public abstract ViewPropertyAnimator setDuration(long duration);
/**
* Returns the current startDelay of property animations. If the startDelay was set on this
* object, that value is returned. Otherwise, the default value of the underlying Animator
* is returned.
*
* @return The startDelay of animations, in milliseconds.
* @see #setStartDelay(long)
*/
public abstract long getStartDelay();
/**
* Sets the startDelay for the underlying animator that animates the requested properties.
* By default, the animator uses the default value for ValueAnimator. Calling this method
* will cause the declared value to be used instead.
*
* @param startDelay The delay of ensuing property animations, in milliseconds. The value
* cannot be negative.
* @return This object, allowing calls to methods in this class to be chained.
*/
public abstract ViewPropertyAnimator setStartDelay(long startDelay);
/**
* Sets the interpolator for the underlying animator that animates the requested properties.
* By default, the animator uses the default interpolator for ValueAnimator. Calling this method
* will cause the declared object to be used instead.
*
* @param interpolator The TimeInterpolator to be used for ensuing property animations.
* @return This object, allowing calls to methods in this class to be chained.
*/
public abstract ViewPropertyAnimator setInterpolator(/*Time*/Interpolator interpolator);
/**
* Sets a listener for events in the underlying Animators that run the property
* animations.
*
* @param listener The listener to be called with AnimatorListener events.
* @return This object, allowing calls to methods in this class to be chained.
*/
public abstract ViewPropertyAnimator setListener(Animator.AnimatorListener listener);
/**
* Starts the currently pending property animations immediately. Calling <code>start()</code>
* is optional because all animations start automatically at the next opportunity. However,
* if the animations are needed to start immediately and synchronously (not at the time when
* the next event is processed by the hierarchy, which is when the animations would begin
* otherwise), then this method can be used.
*/
public abstract void start();
/**
* Cancels all property animations that are currently running or pending.
*/
public abstract void cancel();
/**
* This method will cause the View's <code>x</code> property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setX(float)
*/
public abstract ViewPropertyAnimator x(float value);
/**
* This method will cause the View's <code>x</code> property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setX(float)
*/
public abstract ViewPropertyAnimator xBy(float value);
/**
* This method will cause the View's <code>y</code> property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setY(float)
*/
public abstract ViewPropertyAnimator y(float value);
/**
* This method will cause the View's <code>y</code> property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setY(float)
*/
public abstract ViewPropertyAnimator yBy(float value);
/**
* This method will cause the View's <code>rotation</code> property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setRotation(float)
*/
public abstract ViewPropertyAnimator rotation(float value);
/**
* This method will cause the View's <code>rotation</code> property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setRotation(float)
*/
public abstract ViewPropertyAnimator rotationBy(float value);
/**
* This method will cause the View's <code>rotationX</code> property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setRotationX(float)
*/
public abstract ViewPropertyAnimator rotationX(float value);
/**
* This method will cause the View's <code>rotationX</code> property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setRotationX(float)
*/
public abstract ViewPropertyAnimator rotationXBy(float value);
/**
* This method will cause the View's <code>rotationY</code> property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setRotationY(float)
*/
public abstract ViewPropertyAnimator rotationY(float value);
/**
* This method will cause the View's <code>rotationY</code> property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setRotationY(float)
*/
public abstract ViewPropertyAnimator rotationYBy(float value);
/**
* This method will cause the View's <code>translationX</code> property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setTranslationX(float)
*/
public abstract ViewPropertyAnimator translationX(float value);
/**
* This method will cause the View's <code>translationX</code> property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setTranslationX(float)
*/
public abstract ViewPropertyAnimator translationXBy(float value);
/**
* This method will cause the View's <code>translationY</code> property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setTranslationY(float)
*/
public abstract ViewPropertyAnimator translationY(float value);
/**
* This method will cause the View's <code>translationY</code> property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setTranslationY(float)
*/
public abstract ViewPropertyAnimator translationYBy(float value);
/**
* This method will cause the View's <code>scaleX</code> property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setScaleX(float)
*/
public abstract ViewPropertyAnimator scaleX(float value);
/**
* This method will cause the View's <code>scaleX</code> property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setScaleX(float)
*/
public abstract ViewPropertyAnimator scaleXBy(float value);
/**
* This method will cause the View's <code>scaleY</code> property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setScaleY(float)
*/
public abstract ViewPropertyAnimator scaleY(float value);
/**
* This method will cause the View's <code>scaleY</code> property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setScaleY(float)
*/
public abstract ViewPropertyAnimator scaleYBy(float value);
/**
* This method will cause the View's <code>alpha</code> property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setAlpha(float)
*/
public abstract ViewPropertyAnimator alpha(float value);
/**
* This method will cause the View's <code>alpha</code> property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @return This object, allowing calls to methods in this class to be chained.
* @see View#setAlpha(float)
*/
public abstract ViewPropertyAnimator alphaBy(float value);
}

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginBottom="70dp">
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/history_payment"
android:textColor="#46F"
android:textStyle="bold"
android:textSize="22dp"/>
<ExpandableListView android:id="@+id/list"
android:layout_height="fill_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_marginTop="10dp"
android:groupIndicator="@null" />
</LinearLayout>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="bottom">
<ImageButton android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_save"/>
<TextView android:id="@+id/txtSave"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/btnSave"
android:textStyle="bold"
android:textColor="#FED300"
android:textSize="16dp"/>
</LinearLayout>
</FrameLayout>

View file

@ -0,0 +1,121 @@
package com.adins.mss.coll.commons;
import com.adins.mss.base.util.GsonHelper;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* Created by adityapurwa on 12/03/15.
* Used to convert a hash map to object, because Java is cursed with type erasure.
*/
public class LinkedHashMapToObject {
/**
* Convert a hash map into object.
*
* @param hashMap The hashmap to convert.
* @param metadata Object metadata.
* @param <T> Object type.
* @return Object representing the hash map.
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws NoSuchMethodException
* @throws InstantiationException
*/
public static <T> T convert(LinkedHashMap hashMap, Class<T> metadata, boolean generateUuid) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
Constructor constructor = metadata.getConstructor();
T instance = (T) constructor.newInstance();
Iterator iterator = hashMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = (Map.Entry<String, String>) iterator.next();
String property = String.valueOf(entry.getKey());
String value = String.valueOf(entry.getValue());
Method[] methods = instance.getClass().getMethods();
for (Method m : methods) {
if (m.getName().toLowerCase().equals("set" + property.toLowerCase())) {
Class<?> paramType = m.getParameterTypes()[0];
Object castedValue = resolveValue(value, paramType);
m.invoke(instance, castedValue);
break;
}
}
}
if (generateUuid) {
Method uuidSetter = null;
for (Method m : metadata.getMethods()) {
if (m.getName().toLowerCase().equals("setuuid_" + metadata.getSimpleName().toLowerCase())) {
uuidSetter = m;
break;
}
}
if (uuidSetter != null) {
uuidSetter.invoke(instance, UUID.randomUUID().toString());
}
}
return instance;
}
/**
* Resolve a value based on the type.
*
* @param value Value to resolve.
* @param paramType Type of the value.
* @return Casted value, or original value if the value type is not recognized.
*/
private static Object resolveValue(String value, Class<?> paramType) {
Object castedValue = value;
try {
if (paramType.getSimpleName().equals("Date")) {
castedValue = GsonHelper.fromJson(value, Date.class);
}
if (paramType.getSimpleName().equals("Integer")) {
castedValue = GsonHelper.fromJson(value, Integer.class);
}
if (paramType.getSimpleName().equals("Long")) {
castedValue = GsonHelper.fromJson(value, Long.class);
}
if (paramType.getSimpleName().equals("String")) {
castedValue = GsonHelper.fromJson(value, String.class);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return castedValue;
}
/**
* Convert hash map list into list of object that represents it.
*
* @param <T> Object type.
* @param hashMapList List of hash map.
* @param metadata Object metadata.
* @param generateUuid
* @return List of object that represent the list of hash map.
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws NoSuchMethodException
* @throws InstantiationException
*/
public static <T> List<T> convert(List<LinkedHashMap> hashMapList, Class<T> metadata, boolean generateUuid) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
List<T> converted = new ArrayList<T>();
for (LinkedHashMap hashMap : hashMapList) {
T dummyItem = convert(hashMap, metadata, generateUuid);
converted.add(dummyItem);
}
return converted;
}
}