move clear button implementation to a new custom class
authorDamyan Ivanov <dam+mobileledger@ktnx.net>
Sat, 21 Sep 2019 14:40:09 +0000 (17:40 +0300)
committerDamyan Ivanov <dam+mobileledger@ktnx.net>
Sat, 21 Sep 2019 14:40:09 +0000 (17:40 +0300)
better encapsulation, accessibility concerns about onTouch interception
solved

app/src/main/java/net/ktnx/mobileledger/ui/AutoCompleteTextViewWithClear.java [new file with mode: 0644]
app/src/main/java/net/ktnx/mobileledger/ui/activity/NewTransactionActivity.java
app/src/main/res/layout/content_new_transaction.xml

diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/AutoCompleteTextViewWithClear.java b/app/src/main/java/net/ktnx/mobileledger/ui/AutoCompleteTextViewWithClear.java
new file mode 100644 (file)
index 0000000..8b714da
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright © 2019 Damyan Ivanov.
+ * This file is part of MoLe.
+ * MoLe is free software: you can distribute it and/or modify it
+ * under the term of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your opinion), any later version.
+ *
+ * MoLe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License terms for details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MoLe. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package net.ktnx.mobileledger.ui;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.appcompat.widget.AppCompatAutoCompleteTextView;
+
+import net.ktnx.mobileledger.R;
+
+public final class AutoCompleteTextViewWithClear extends AppCompatAutoCompleteTextView {
+    private boolean hadText = false;
+
+    public AutoCompleteTextViewWithClear(Context context) {
+        super(context);
+    }
+    public AutoCompleteTextViewWithClear(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+    public AutoCompleteTextViewWithClear(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+    @Override
+    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+        if (focused) {
+            if (getText().length() > 0) {
+                showClearDrawable();
+            }
+        }
+        else {
+            hideClearDrawable();
+        }
+
+        super.onFocusChanged(focused, direction, previouslyFocusedRect);
+    }
+    private void hideClearDrawable() {
+        setCompoundDrawablesRelative(null, null, null, null);
+    }
+    private void showClearDrawable() {
+        setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_clear_black_24dp, 0);
+    }
+    @Override
+    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
+        final boolean hasText = text.length() > 0;
+
+        if (hadText && !hasText) hideClearDrawable();
+        if (!hadText && hasText) showClearDrawable();
+
+        hadText = hasText;
+
+        super.onTextChanged(text, start, lengthBefore, lengthAfter);
+    }
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (event.getAction() == MotionEvent.ACTION_UP) if (getText().length() > 0) {
+            boolean clearClicked = false;
+            final float x = event.getX();
+            final int vw = getWidth();
+            // start, top, end, bottom (end == 2)
+            Drawable dwb = getCompoundDrawablesRelative()[2];
+            if (dwb != null) {
+                final int dw = dwb.getBounds().width();
+                if (getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
+                    if ((x > vw - dw)) clearClicked = true;
+                }
+                else {
+                    if (x < vw - dw) clearClicked = true;
+                }
+                if (clearClicked) {
+                    setText("");
+                    requestFocus();
+                    performClick();
+                    return true;
+                }
+            }
+        }
+
+        return super.onTouchEvent(event);
+    }
+    @Override
+    public boolean performClick() {
+        return super.performClick();
+    }
+}
index 9062f54..ac01c93 100644 (file)
@@ -19,7 +19,6 @@ package net.ktnx.mobileledger.ui.activity;
 
 import android.annotation.SuppressLint;
 import android.database.Cursor;
-import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.text.Editable;
@@ -54,6 +53,7 @@ import net.ktnx.mobileledger.model.Data;
 import net.ktnx.mobileledger.model.LedgerTransaction;
 import net.ktnx.mobileledger.model.LedgerTransactionAccount;
 import net.ktnx.mobileledger.model.MobileLedgerProfile;
+import net.ktnx.mobileledger.ui.AutoCompleteTextViewWithClear;
 import net.ktnx.mobileledger.ui.DatePickerFragment;
 import net.ktnx.mobileledger.ui.OnSwipeTouchListener;
 import net.ktnx.mobileledger.utils.Globals;
@@ -105,7 +105,6 @@ public class NewTransactionActivity extends ProfileThemedActivity
         MLDB.hookAutocompletionAdapter(this, tvDescription, MLDB.DESCRIPTION_HISTORY_TABLE,
                 "description", false, findViewById(R.id.new_transaction_acc_1), this, mProfile);
         hookTextChangeListener(tvDescription);
-        hookClearClickListener(tvDescription);
 
         progress = findViewById(R.id.save_transaction_progress);
         fab = findViewById(R.id.fab);
@@ -120,75 +119,6 @@ public class NewTransactionActivity extends ProfileThemedActivity
 
         check_transaction_submittable();
     }
-    private void hookClearClickListener(AutoCompleteTextView v) {
-        final TextWatcher w = new TextWatcher() {
-            private boolean hasText;
-            private boolean hadText;
-            @Override
-            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-                hadText = s.length() > 0;
-            }
-            @Override
-            public void onTextChanged(CharSequence s, int start, int before, int count) {
-
-            }
-            @Override
-            public void afterTextChanged(Editable s) {
-                hasText = s.length() > 0;
-
-                if (hadText && !hasText) {
-                    v.setCompoundDrawablesRelative(null, null, null, null);
-                }
-                if (!hadText && hasText) {
-                    v.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0,
-                            R.drawable.ic_clear_black_24dp, 0);
-                }
-            }
-        };
-        View.OnFocusChangeListener prevFocusListener = v.getOnFocusChangeListener();
-        v.setOnFocusChangeListener((v12, hasFocus) -> {
-            if (hasFocus) {
-                if (((TextView) v12).getText().length() > 0) {
-                    ((TextView) v12).setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0,
-                            R.drawable.ic_clear_black_24dp, 0);
-                }
-                ((TextView) v12).addTextChangedListener(w);
-            }
-            else {
-                ((TextView) v12).removeTextChangedListener(w);
-                ((TextView) v12).setCompoundDrawables(null, null, null, null);
-            }
-
-            if (prevFocusListener != null) prevFocusListener.onFocusChange(v12, hasFocus);
-        });
-
-        v.setOnTouchListener((v1, event) -> {
-            if (event.getAction() == MotionEvent.ACTION_UP)
-                if (((TextView) v1).getText().length() > 0) {
-                    boolean clearClicked = false;
-                    final float x = event.getX();
-                    final int vw = v1.getWidth();
-                    // start, top, end, bottom (end == 2)
-                    Drawable dwb = ((TextView) v1).getCompoundDrawablesRelative()[2];
-                    if (dwb != null) {
-                        final int dw = dwb.getBounds().width();
-                        if (v1.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
-                            if ((x > vw - dw)) clearClicked = true;
-                        }
-                        else {
-                            if (x < vw - dw) clearClicked = true;
-                        }
-                        if (clearClicked) {
-                            ((TextView) v1).setText("");
-                            v1.requestFocus();
-                            return true;
-                        }
-                    }
-                }
-            v.performClick();
-            return false;
-        });
-    }
     @Override
     protected void initProfile() {
         String profileUUID = getIntent().getStringExtra("profile_uuid");
@@ -387,7 +317,7 @@ public class NewTransactionActivity extends ProfileThemedActivity
 
     }
     private TableRow doAddAccountRow(boolean focus) {
-        final AutoCompleteTextView acc = new AutoCompleteTextView(this);
+        final AutoCompleteTextView acc = new AutoCompleteTextViewWithClear(this);
         acc.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT,
                 TableRow.LayoutParams.WRAP_CONTENT, 9f));
         acc.setHint(R.string.new_transaction_account_hint);
@@ -438,7 +368,6 @@ public class NewTransactionActivity extends ProfileThemedActivity
         MLDB.hookAutocompletionAdapter(this, acc, MLDB.ACCOUNTS_TABLE, "name", true, amt, null,
                 mProfile);
         hookTextChangeListener(acc);
-        hookClearClickListener(acc);
         hookTextChangeListener(amt);
 
         return row;
index e8b356b..b4ff8c6 100644 (file)
@@ -63,7 +63,7 @@
                     app:layout_constraintStart_toStartOf="parent"
                     app:layout_constraintTop_toTopOf="parent" />
 
-                <AutoCompleteTextView
+                <net.ktnx.mobileledger.ui.AutoCompleteTextViewWithClear
                     android:id="@+id/new_transaction_description"
                     android:layout_width="0dp"
                     android:layout_height="wrap_content"