安卓自动完成

4

我在Android方面仍然是个新手,正在学习自动完成文本框的使用。我正在使用MultiAutoCompleteTextView来填充文本框并从字符串数组中提供提示。数组中的每个字符串都是一个具有ID的对象的名称。因此,我的问题有两个:

  • 在用户单击自动完成列表中的给定条目后,如何找到与用户选择的字符串对应的ID?

  • 是否有可能创建一种“类似Facebook的框”,将从自动补全列表中选择的项目放在该框中,该框就像原子单位一样工作,用户可以通过按X来删除它们? (类似于stack overflow标签框中每个标签发生的情况)

先谢谢。

3个回答

4
Android具有“Chips”小部件的源代码,这些小部件用于邮件应用程序中。它们是表示收件人的用户的芯片。它们看起来就像您所提到的Facebook小部件:带有“X”取消的名称。我能够调整代码并将其用于我的自己的需要,但说实话,它非常复杂,我花了很长时间才理解它。
核心原则是使用Spannable字符串并手动绘制背景和“X”的位图。
以下是Android源代码:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/com/android/ex/chips/RecipientEditTextView.java 核心方法是createSelectedChip、constructChipSpan。

嗯,很好,这样就可以了,谢谢!我本来以为在Android中有一种“预定义”的方法可以做到这一点,但是这样更加灵活 :) - Sagito
我们可以在我们的项目中使用这个芯片库吗?还是有任何许可问题? - Raneez Ahmed
自从我发布了我的答案后,我已经发现了这个包:https://github.com/splitwise/TokenAutoComplete - Cody Caughlan

4
我在github上开源了一个TokenAutoComplete,可以很好地解决这个问题。似乎没有更简单的答案。以下是您所描述的基本实现:
public class ContactsCompletionView extends TokenCompleteTextView {
    public ContactsCompletionView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected View getViewForObject(Object object) {
        Person p = (Person)object;

        LayoutInflater l = (LayoutInflater)getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        LinearLayout view = (LinearLayout)l.inflate(R.layout.contact_token, (ViewGroup)ContactsCompletionView.this.getParent(), false);
        ((TextView)view.findViewById(R.id.name)).setText(p.getName());

        return view;
    }

    @Override
    protected Object defaultObject(String completionText) {
        //Stupid simple example of guessing if we have an email or not
        int index = completionText.indexOf('@');
        if (index == -1) {
            return new Person(completionText, completionText.replace(" ", "") + "@example.com");
        } else {
            return new Person(completionText.substring(0, index), completionText);
        }
    }
}

联系人令牌的布局代码(您需要找到自己的x drawable)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:background="@drawable/token_background">
    <TextView android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white"
        android:textSize="14sp"
        android:text="Test Me"
        android:padding="2dp" />

    <ImageView
        android:layout_height="10dp"
        android:layout_width="10dp"
        android:src="@drawable/x"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="3dp"
        android:layout_marginRight="5dp" />
</LinearLayout>

令牌背景可绘制

<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <solid android:color="#ffafafaf" />
    <corners
        android:topLeftRadius="5dp"
        android:bottomLeftRadius="5dp"
        android:topRightRadius="5dp"
        android:bottomRightRadius="5dp" />
</shape>

人员对象代码

public class Person implements Serializable {
    private String name;
    private String email;

    public Person(String n, String e) { name = n; email = e; }

    public String getName() { return name; }
    public String getEmail() { return email; }

    @Override
    public String toString() { return name; }
}

示例活动

public class TokenActivity extends Activity {
    ContactsCompletionView completionView;
    Person[] people;
    ArrayAdapter<Person> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        people = new Person[]{
                new Person("Marshall Weir", "marshall@example.com"),
                new Person("Margaret Smith", "margaret@example.com"),
                new Person("Max Jordan", "max@example.com"),
                new Person("Meg Peterson", "meg@example.com"),
                new Person("Amanda Johnson", "amanda@example.com"),
                new Person("Terry Anderson", "terry@example.com")
        };

        adapter = new ArrayAdapter<Person>(this, android.R.layout.simple_list_item_1, people);

        completionView = (ContactsCompletionView)findViewById(R.id.searchView);
        completionView.setAdapter(adapter);
        completionView.setTokenClickStyle(TokenCompleteTextView.TokenClickStyle.Delete);
    }
}

布局代码

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.tokenautocomplete.ContactsCompletionView
        android:id="@+id/searchView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</RelativeLayout>

这是您获得的界面:

Image of working TokenAutoComplete activity


如何获取所有选定的值?我的意思是,如果用户输入的电子邮件地址不在定义的数组列表中,那么我们如何获取它呢? - Scorpion
getObjects将返回字段中所有令牌的对象。如果是新对象,则它将是您从defaultObject返回的值。 - Marshall Weir
您好,我有一个问题。我想在点击叉号图像时删除。请问如何使用令牌样式实现这个功能。 - Rajasekhar
没有一种方法可以在单击令牌的特定部分时进行删除。项目文档中有一些注释,说明如何在选择时更改令牌,并且有一种令牌样式,第一次单击选择令牌,第二次单击删除它。我已经构建了大多数用途,以便在选择令牌时显示X,以便清楚地表明用户打算在第二次单击时将其删除。通常,我认为令牌太小,无法具有多个单击目标。 - Marshall Weir

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接