blob: a2fffed83d4ce895cc020f2210a88ba6e0514833 [file] [log] [blame]
package foo.bar.filled;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStructure;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
public class CustomLinearLayout extends LinearLayout {
static final boolean VIRTUAL = false;
public CustomLinearLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
if (VIRTUAL) {
getViewTreeObserver().addOnGlobalFocusChangeListener((oldFocus, newFocus) -> {
AutofillManager autofillManager = getContext().getSystemService(
AutofillManager.class);
if (oldFocus != null) {
autofillManager.notifyViewExited(CustomLinearLayout.this,
oldFocus.getAccessibilityViewId());
}
if (newFocus != null) {
Rect bounds = new Rect();
newFocus.getBoundsOnScreen(bounds);
autofillManager.notifyViewEntered(CustomLinearLayout.this,
newFocus.getAccessibilityViewId(), bounds);
}
});
}
}
@Override
public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
if (!VIRTUAL) {
super.dispatchProvideAutofillStructure(structure, flags);
} else {
onProvideAutofillVirtualStructure(structure, flags);
}
}
@Override
public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
if (!VIRTUAL) {
return;
}
populateViewStructure(this, structure);
onProvideAutofillVirtualStructureRecursive(this, structure);
}
@Override
public void autofill(SparseArray<AutofillValue> values) {
final int valueCount = values.size();
for (int i = 0; i < valueCount; i++) {
final int virtualId = values.keyAt(i);
final AutofillValue value = values.valueAt(i);
View view = findViewByAccessibilityIdTraversal(virtualId);
if (view instanceof EditText && !TextUtils.isEmpty(value.getTextValue())) {
EditText editText = (EditText) view;
editText.setText(value.getTextValue());
}
}
}
private void onProvideAutofillVirtualStructureRecursive(View view, ViewStructure node) {
if (node == null) {
return;
}
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
final int childCount = viewGroup.getChildCount();
node.setChildCount(childCount);
for (int i = 0; i < childCount; i++) {
View child = viewGroup.getChildAt(i);
ViewStructure chlidNode = node.newChild(i);
chlidNode.setAutofillId(node, child.getAccessibilityViewId());
populateViewStructure(child, chlidNode);
onProvideAutofillVirtualStructureRecursive(child, chlidNode);
}
}
}
private void populateViewStructure(View view, ViewStructure structure) {
if (view.getId() != NO_ID) {
String pkg, type, entry;
try {
final Resources res = getResources();
entry = res.getResourceEntryName(view.getId());
type = res.getResourceTypeName(view.getId());
pkg = res.getResourcePackageName(view.getId());
} catch (Resources.NotFoundException e) {
entry = type = pkg = null;
}
structure.setId(view.getId(), pkg, type, entry);
} else {
structure.setId(view.getId(), null, null, null);
}
Rect rect = structure.getTempRect();
view.getDrawingRect(rect);
structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
structure.setVisibility(VISIBLE);
structure.setEnabled(view.isEnabled());
if (view.isClickable()) {
structure.setClickable(true);
}
if (view.isFocusable()) {
structure.setFocusable(true);
}
if (view.isFocused()) {
structure.setFocused(true);
}
if (view.isAccessibilityFocused()) {
structure.setAccessibilityFocused(true);
}
if (view.isSelected()) {
structure.setSelected(true);
}
if (view.isLongClickable()) {
structure.setLongClickable(true);
}
CharSequence cname = view.getClass().getName();
structure.setClassName(cname != null ? cname.toString() : null);
structure.setContentDescription(view.getContentDescription());
if (view instanceof TextView) {
TextView textView = (TextView) view;
structure.setText(textView.getText(), textView.getSelectionStart(),
textView.getSelectionEnd());
}
structure.setAutofillHints(view.getAutofillHints());
structure.setAutofillType(view.getAutofillType());
structure.setAutofillValue(view.getAutofillValue());
}
}