Android-Prevent dismissal of dropdown in AutoCompl

2019-07-03 02:40发布

Even though I'm setting the setOnItemClickListener on the AutoCompleteTextView and performing some custom operations in it, once that method is done, the list dismisses and prints out the object.toString in the editbox.

I want to prevent dismissal of the dropdown on item select and would also like it to not replace the edit box. How can I achieve this ?

6条回答
叼着烟拽天下
2楼-- · 2019-07-03 03:23

Overriding replaceText without calling super works fine (prevents entering suggested text into AutoCompleteTextView), but overriding dismissDropDown causes not-dismissing dropdown not only when item clicked, but also when onBackPressed, touched outside dialog etc...

I've ended with NOT using setOnItemClickListener method from AutoCompleteTextView at all. I'm creating custom onClick in my custom ArrayAdapter and set it for all Views returned by getView method

View.OnClickListener onClick=null;

public void setOnItemClickListener(View.OnClickListener onClick) {
    this.onClick=onClick;
    /*this.onClick=new View.OnClickListener(){
        @Override
        public void onClick(View v) {
            if(v.getTag()==null)
                return;
            Integer position = (Integer) v.getTag();
            Toast.makeText(v.getContext(), "position: "+postion, Toast.LENGTH_SHORT).show();
        }
    });*/
}

@NonNull
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
    ... call super/inflate convertView and do your stuff here
    setCustomOnClick(convertView, position);
    return convertView;
}

private void setCustomOnClick(final View view, final int position){
    view.setTag(position); 
    view.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v) {
            if(onClick==null)
                return;
            // inside called onClick method v.getTag() will return pressed position
            onClick.onClick(v);
        }
    });
}

in fact setting onClick for whole view will cover "original" always-dismissing and always-replacing-text onClick (not called at all then). Remember about adding custom graphic representation, when pressed (ripple/selector are shown when "original" onClick called only)

I've needed also always-visible functionality, because my autocomplete must always show first position (functional), even when there is no suggestions (if present then shown below on positions 1+)

public class AlwaysVisibleAutoCompleteTextView extends AppCompatAutoCompleteTextView {

    private boolean showAlways=true;

    public AlwaysVisibleAutoCompleteTextView(Context context) {
        super(context);
    }

    public AlwaysVisibleAutoCompleteTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AlwaysVisibleAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void setShowAlways(boolean showAlways) {
        this.showAlways = showAlways;
    }

    @Override
    public boolean enoughToFilter() {
        return showAlways || super.enoughToFilter();
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        showDropDownIfFocused();
    }

    private void showDropDownIfFocused() {
        if (enoughToFilter() && isFocused() && getWindowVisibility() == View.VISIBLE)
            showDropDown();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        showDropDownIfFocused();
    }

}

when AlwaysVisibleAutoCompleteTextView is focused, but dropdown dismissed and user press view again, then dropdown is not showing, because focus state not changing (onFocusChanged not called), so

autoComplete.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) 
                autoComplete.showDropDown();
            return false;
        }
    });

If you aren't planning using setOnTouchListener for your AutoCompleteTextView for any other purpose, then OnTouchListener may be set inside AlwaysVisibleAutoCompleteTextView class (in every constructor)

查看更多
叛逆
3楼-- · 2019-07-03 03:27

well at least it seems like they are planning to add this in near future.

/**
 * Sets whether the drop-down should remain visible as long as there is there is
 * {@link #enoughToFilter()}.  This is useful if an unknown number of results are expected
 * to show up in the adapter sometime in the future.
 *
 * The drop-down will occupy the entire screen below {@link #getDropDownAnchor} regardless
 * of the size or content of the list.  {@link #getDropDownBackground()} will fill any space
 * that is not used by the list.
 *
 * @param dropDownAlwaysVisible Whether to keep the drop-down visible.
 *
 * @hide Pending API council approval
 */
public void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) {
    mPopup.setDropDownAlwaysVisible(dropDownAlwaysVisible);
}
查看更多
啃猪蹄的小仙女
4楼-- · 2019-07-03 03:31

First Question - Prevent dropdown dismissal:

Solved below.

Second Question - Prevent text replacement: (For others interested)

You can extend AutoCompleteTextView and override

protected void replaceText(CharSequence text) {}

to do nothing.

As others mentioned, overriding performCompletion() won't help here.

查看更多
The star\"
5楼-- · 2019-07-03 03:33

edit,new answer: this worked for me but it closes for a sec,and opens again.

            class task extends TimerTask {

            @Override
            public void run() {
                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        autoComplete.showDropDown();
                    }
                });
            }
       };
    autoComplete.setOnItemClickListener(new OnItemClickListener() {

        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {

             new Timer().schedule(new task(),0, 10);
        }

    });
查看更多
狗以群分
6楼-- · 2019-07-03 03:35

I added an onClickListener to the entire custom row layout that I was using for the dropdown adapter. This way whenever the row is clicked, my row onClickListener is invoked and the default one for the dropdown is not.

查看更多
趁早两清
7楼-- · 2019-07-03 03:44

I also want to implement the same i used below code to implement it.

Create a custom class and extend AutoCompleteTextView.

Override dismissDropDown() method and remove the super call from it. Will work for you.

public class CustomAutoComplete extends AutoCompleteTextView {
    public NoSelectionAutoComplete(Context context) {
        super(context);
    }

    public NoSelectionAutoComplete(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public NoSelectionAutoComplete(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void replaceText(CharSequence text) {

    }

    @Override
    public void dismissDropDown() {

    }
}
查看更多
登录 后发表回答