diff options
Diffstat (limited to 'input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.kt')
-rw-r--r-- | input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.kt | 186 |
1 files changed, 86 insertions, 100 deletions
diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.kt b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.kt index c737fe4c..36c43439 100644 --- a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.kt +++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.kt @@ -21,7 +21,6 @@ import android.graphics.Color import android.graphics.Paint import android.graphics.Paint.Style import android.graphics.Rect -import android.text.TextUtils import android.util.AttributeSet import android.util.Log import android.util.SparseArray @@ -32,6 +31,7 @@ import android.view.autofill.AutofillManager import android.view.autofill.AutofillValue import android.widget.EditText import android.widget.TextView +import com.example.android.autofillframework.CommonUtil.TAG import com.example.android.autofillframework.CommonUtil.bundleToString import com.example.android.autofillframework.R import java.util.Arrays @@ -42,33 +42,30 @@ import java.util.Arrays */ class CustomVirtualView(context: Context, attrs: AttributeSet) : View(context, attrs) { - private val mLines = ArrayList<Line>() - private val mItems = SparseArray<Item>() - private val mAfm: AutofillManager = context.getSystemService(AutofillManager::class.java) - - private var mFocusedLine: Line? = null - private val mTextPaint: Paint = Paint() - private val mTextHeight: Int = 90 - private val mTopMargin: Int = 100 - private val mLeftMargin: Int = 100 - private val mVerticalGap: Int = 10 - private val mLineLength: Int = mTextHeight + mVerticalGap - private val mFocusedColor: Int = Color.RED - private val mUnfocusedColor: Int = Color.BLACK - - private val mUsernameLine: Line - private val mPasswordLine: Line - - init { - mTextPaint.style = Style.FILL - mTextPaint.textSize = mTextHeight.toFloat() - mUsernameLine = addLine("usernameField", context.getString(R.string.username_label), - arrayOf(View.AUTOFILL_HINT_USERNAME), " ", true) - mPasswordLine = addLine("passwordField", context.getString(R.string.password_label), - arrayOf(View.AUTOFILL_HINT_PASSWORD), " ", false) - - Log.d(TAG, "Text height: " + mTextHeight) + val usernameText: CharSequence + get() = usernameLine.fieldTextItem.text + val passwordText: CharSequence + get() = passwordLine.fieldTextItem.text + private var nextId: Int = 0 + private val lines = ArrayList<Line>() + private val items = SparseArray<Item>() + private val autofillManager = context.getSystemService(AutofillManager::class.java) + private var focusedLine: Line? = null + private val textHeight = 90 + private val textPaint = Paint().apply { + style = Style.FILL + textSize = textHeight.toFloat() } + private val topMargin = 100 + private val leftMargin = 100 + private val verticalGap = 10 + private val lineLength = textHeight + verticalGap + private val focusedColor = Color.RED + private val unfocusedColor = Color.BLACK + private val usernameLine = addLine("usernameField", context.getString(R.string.username_label), + arrayOf(View.AUTOFILL_HINT_USERNAME), " ", true) + private val passwordLine = addLine("passwordField", context.getString(R.string.password_label), + arrayOf(View.AUTOFILL_HINT_PASSWORD), " ", false) override fun autofill(values: SparseArray<AutofillValue>) { // User has just selected a Dataset from the list of autofill suggestions. @@ -76,15 +73,15 @@ class CustomVirtualView(context: Context, attrs: AttributeSet) : View(context, a // to fill a specific autofillable view. Now we have to update the UI based on the // AutofillValues in the list. Log.d(TAG, "autofill(): " + values) - for (i in 0..values.size() - 1) { + for (i in 0 until values.size()) { val id = values.keyAt(i) val value = values.valueAt(i) - mItems[id]?.let { item -> - if (item.editable) { + items[id]?.apply { + if (editable) { // Set the item's text to the text wrapped in the AutofillValue. - item.text = value.textValue + text = value.textValue } else { - Log.w(TAG, "Item for autofillId $id is not editable: $item") + Log.w(TAG, "Item for autofillId $id is not editable: $this") } } } @@ -94,24 +91,23 @@ class CustomVirtualView(context: Context, attrs: AttributeSet) : View(context, a override fun onProvideAutofillVirtualStructure(structure: ViewStructure, flags: Int) { // Build a ViewStructure to pack in AutoFillService requests. structure.setClassName(javaClass.name) - val childrenSize = mItems.size() + val childrenSize = items.size() Log.d(TAG, "onProvideAutofillVirtualStructure(): flags = " + flags + ", items = " + childrenSize + ", extras: " + bundleToString(structure.extras)) var index = structure.addChildCount(childrenSize) - for (i in 0..childrenSize - 1) { - val item = mItems.valueAt(i) + for (i in 0 until childrenSize) { + val item = items.valueAt(i) Log.d(TAG, "Adding new child at index $index: $item") - val child = structure.newChild(index) - child.setAutofillId(structure.getAutofillId(), item.id) - child.setAutofillHints(item.hints) - child.setAutofillType(item.type) - child.setDataIsSensitive(!item.sanitized) - if (TextUtils.getTrimmedLength(item.text) > 0) { - child.setAutofillValue(AutofillValue.forText(item.text)) + structure.newChild(index).apply { + setAutofillId(structure.autofillId, item.id) + setAutofillHints(item.hints) + setAutofillType(item.type) + setDataIsSensitive(!item.sanitized) + setAutofillValue(AutofillValue.forText(item.text)) + setFocused(item.focused) + setId(item.id, context.packageName, null, item.line.idEntry) + setClassName(item.className) } - child.setFocused(item.focused) - child.setId(item.id, context.packageName, null, item.line.idEntry) - child.setClassName(item.className) index++ } } @@ -119,74 +115,71 @@ class CustomVirtualView(context: Context, attrs: AttributeSet) : View(context, a override fun onDraw(canvas: Canvas) { super.onDraw(canvas) - Log.d(TAG, "onDraw: " + mLines.size + " lines; canvas:" + canvas) + Log.d(TAG, "onDraw: " + lines.size + " lines; canvas:" + canvas) var x: Float - var y = (mTopMargin + mLineLength).toFloat() - for (line in mLines) { - x = mLeftMargin.toFloat() - Log.v(TAG, "Drawing '" + line + "' at " + x + "x" + y) - mTextPaint.color = if (line.fieldTextItem.focused) mFocusedColor else mUnfocusedColor - val readOnlyText = line.labelItem.text.toString() + ": [" - val writeText = line.fieldTextItem.text.toString() + "]" + var y = (topMargin + lineLength).toFloat() + + lines.forEach { + x = leftMargin.toFloat() + Log.v(TAG, "Drawing $it at x=$x, y=$y") + textPaint.color = if (it.fieldTextItem.focused) focusedColor else unfocusedColor + val readOnlyText = it.labelItem.text.toString() + ": [" + val writeText = it.fieldTextItem.text.toString() + "]" // Paints the label first... - canvas.drawText(readOnlyText, x, y, mTextPaint) + canvas.drawText(readOnlyText, x, y, textPaint) // ...then paints the edit text and sets the proper boundary - val deltaX = mTextPaint.measureText(readOnlyText) + val deltaX = textPaint.measureText(readOnlyText) x += deltaX - line.bounds.set(x.toInt(), (y - mLineLength).toInt(), - (x + mTextPaint.measureText(writeText)).toInt(), y.toInt()) - Log.d(TAG, "setBounds(" + x + ", " + y + "): " + line.bounds) - canvas.drawText(writeText, x, y, mTextPaint) - y += mLineLength.toFloat() + it.bounds.set(x.toInt(), (y - lineLength).toInt(), + (x + textPaint.measureText(writeText)).toInt(), y.toInt()) + Log.d(TAG, "setBounds(" + x + ", " + y + "): " + it.bounds) + canvas.drawText(writeText, x, y, textPaint) + y += lineLength.toFloat() } } override fun onTouchEvent(event: MotionEvent): Boolean { val y = event.y.toInt() - Log.d(TAG, "Touched: y=$y, range=$mLineLength, top=$mTopMargin") - var lowerY = mTopMargin + Log.d(TAG, "Touched: y=$y, range=$lineLength, top=$topMargin") + var lowerY = topMargin var upperY = -1 - for (i in mLines.indices) { - upperY = lowerY + mLineLength - val line = mLines[i] - Log.d(TAG, "Line $i ranges from $lowerY to $upperY") - if (lowerY <= y && y <= upperY) { - Log.d(TAG, "Removing focus from " + mFocusedLine) - mFocusedLine?.changeFocus(false) + for (line in lines) { + upperY = lowerY + lineLength + Log.d(TAG, "Line $line ranges from $lowerY to $upperY") + if (y in lowerY..upperY) { + Log.d(TAG, "Removing focus from " + focusedLine) + focusedLine?.changeFocus(false) Log.d(TAG, "Changing focus to " + line) - mFocusedLine = line - mFocusedLine?.changeFocus(true) + focusedLine = line.apply { changeFocus(true) } invalidate() break } - lowerY += mLineLength + lowerY += lineLength } return super.onTouchEvent(event) } - val usernameText: CharSequence - get() = mUsernameLine.fieldTextItem.text - - val passwordText: CharSequence - get() = mPasswordLine.fieldTextItem.text - fun resetFields() { - mUsernameLine.reset() - mPasswordLine.reset() + usernameLine.reset() + passwordLine.reset() postInvalidate() } - private fun addLine(idEntry: String, label: String, hints: Array<String>, text: String, sanitized: Boolean): Line { - val line = Line(idEntry, label, hints, text, sanitized) - mLines.add(line) - mItems.put(line.labelItem.id, line.labelItem) - mItems.put(line.fieldTextItem.id, line.fieldTextItem) - return line + private fun addLine(idEntry: String, label: String, hints: Array<String>, text: String, + sanitized: Boolean) = Line(idEntry, label, hints, text, sanitized).also { + lines.add(it) + items.apply { + put(it.labelItem.id, it.labelItem) + put(it.fieldTextItem.id, it.fieldTextItem) + } } - private class Item internal constructor(val line: Line, val id: Int, val hints: Array<String>?, - val type: Int, var text: CharSequence, - val editable: Boolean, val sanitized: Boolean) { + private inner class Item internal constructor( + val line: Line, + val id: Int, + val hints: Array<String>?, + val type: Int, var text: CharSequence, val editable: Boolean, + val sanitized: Boolean) { var focused = false override fun toString(): String { @@ -213,15 +206,15 @@ class CustomVirtualView(context: Context, attrs: AttributeSet) : View(context, a if (focused) { val absBounds = absCoordinates Log.d(TAG, "focus gained on " + fieldTextItem.id + "; absBounds=" + absBounds) - mAfm.notifyViewEntered(this@CustomVirtualView, fieldTextItem.id, absBounds) + autofillManager.notifyViewEntered(this@CustomVirtualView, fieldTextItem.id, absBounds) } else { Log.d(TAG, "focus lost on " + fieldTextItem.id) - mAfm.notifyViewExited(this@CustomVirtualView, fieldTextItem.id) + autofillManager.notifyViewExited(this@CustomVirtualView, fieldTextItem.id) } } - private // Must offset the boundaries so they're relative to the CustomView. - val absCoordinates: Rect + private val absCoordinates: Rect + // Must offset the boundaries so they're relative to the CustomView. get() { val offset = IntArray(2) getLocationOnScreen(offset) @@ -242,11 +235,4 @@ class CustomVirtualView(context: Context, attrs: AttributeSet) : View(context, a fieldTextItem.focused } } - - companion object { - - private val TAG = "CustomView" - - private var nextId: Int = 0 - } }
\ No newline at end of file |