Boardy
Boardy

Reputation: 36223

Set cursor position using setSelection on AutoCompleteTextView which is dynamically generated

I am working on a project which uses a TableLayout, and the user can add a new row to the table layout. Each new row is inflated as a new view and then the view is added to the table layout. One of the controls within the row is an AutoCompleteTextView.

The user can start typing into the AutCompleteTextView and then select one of the items in the suggestion list, when the user selects the item, the selected item is added to the text box as expected, but I want to then set the cursor position as the user can then change the value of the text. For example, the selected item might be sometext() but they can amend the text after selecting it to become sometext(25), so I am trying to set the position of the cursor within the brackets.

This is working fine for one AutoCompleteTextView in the layout but I can't figure out how to do it when its dynamically generated.

I'm finding the AutoCompleteTextView from the inflated layout and creating a set on item click listener, and using the view parameter in the OnItemClick function to ensure I am using the correct view that triggered the event handler, but on the setSelection I am getting an exception java.lang.ClassCastException: android.support.v7.widget.AppCompatTextView cannot be cast to android.widget.AutoCompleteTextView

Below is the code I am using:

private void addRow()
    {
        TableRow row = (TableRow)LayoutInflater.from(this).inflate(R.layout.create_table_column_row, createTable, false);
        txtColumnName = row.findViewById(R.id.txtColumnName);
        txtDataType = row.findViewById(R.id.txtDataType);
        txtDataType.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                txtDataType.showDropDown();
            }
        });
        txtDataType.setOnItemClickListener(new AdapterView.OnItemClickListener()
        {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id)
            {
                String selectedItem = parent.getItemAtPosition(position).toString();
                //Check if the string has a ( and if so, set the cursor to be just after it so the user can enter the size
                int bracketPos = selectedItem.indexOf("(");
                if (bracketPos > 0)
                {
                    //Crashes on this line
                    ((AutoCompleteTextView)view).setSelection(bracketPos+1);
                }
            }
        });

        List<String> datatypes = Arrays.asList(getResources().getStringArray(R.array.table_datatypes));
        datatypeAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, datatypes);
        txtDataType.setAdapter(datatypeAdapter);
        rowViews.add(row);
        createTable.addView(row);
    }

I tried casting the view to AppCompatTextView but then this doesn't have the setSelection() method.

Upvotes: 2

Views: 833

Answers (1)

Cheticamp
Cheticamp

Reputation: 62831

The view in onItemClick() is the AppCompatTextView that is clicked in the drop down box for the AutoCompleteTextView. That is why you can't cast it.

Since you have multiple AutoCompleteTextViews, use a focus change listener to capture which AutoCompleteTextView is being addressed by the user. You can then use that value to set the position of the cursor.

private AutoCompleteTextView textView;
private AutoCompleteTextView mAuto;

textView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        mAuto = (AutoCompleteTextView) v;
    }
});

textView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Log.d("MainActivity", "<<<<onItemClicked");
        int bracketPos = textView.getText().toString().indexOf("(");
        if (bracketPos > 0) {
            mAuto.setSelection(bracketPos + 1);
        }
    }
});

I believe that the AutoCompleteTextView is already populated when this method is called, so you could just search for ( within that field.


Here is a slightly different way. After

txtDataType = row.findViewById(R.id.txtDataType);

add

txtDataType.setOnClickListener(new View.OnClickListener() {
    private AutoCompleteTextView mAutoView;

    @Override
    public void onClick(View v) {
        mAutoView = (AutoCompleteTextView) v;
        mAutoView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Log.d("MainActivity", "<<<<onItemClicked");
                int bracketPos = mAutoView.getText().toString().indexOf("(");
                if (bracketPos > 0) {
                    mAutoView.setSelection(bracketPos + 1);
                }
            }
        });
    }
});

You can delete your other listeners.

Upvotes: 1

Related Questions