【问题标题】:Spinner with custom drop-down view not triggering onItemSelected()具有自定义下拉视图的微调器未触发 onItemSelected()
【发布时间】:2016-06-14 02:33:41
【问题描述】:

我有一个使用自定义适配器的 Spinner,其中 getDropDownView() 被覆盖。自定义下拉视图中的每一项都由一个 TextView 和一个 Button 组成。

但是,当我运行我的代码时,微调器下拉项显示正常,但单击它们没有任何作用。微调器下拉菜单保持打开状态,并且未触发 spinner.onItemSelected()。

drop_down_item.xml

<RelativeLayout 
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <TextView
        android:id="@+id/dropdown_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:singleLine="true" />
    <Button
        android:id="@+id/dropdown_button"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_alignParentRight="true"
        android:text="Remove"/>
</RelativeLayout>

自定义适配器代码

public View getDropDownView(final int position, View convertView, ViewGroup parent) {

    LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.drop_down_item, parent, false);

    TextView textView = (TextView) rowView.findViewById(R.id.dropdown_text);
    textView.setText(mValues.get(position));        
    Button buttonView = (Button) rowView.findViewById(R.id.dropdown_button));

   return rowView;
 }

我使用以下代码创建我的微调器和适配器:

spinner = (Spinner) findViewById(R.id.my_spinner);
MyAdapter adapter = new MyAdapter(getViewContext(), R.layout.spinner_item, values);
adapter.setDropDownViewResource(R.layout.drop_down_item);
spinner.setAdapter(adapter);
...
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
        // Do something here - but this never runs
    }
});

所以我不知道为什么 onItemSelected() 不再被调用?

我想知道是否需要在下拉 TextView 上放置一个点击侦听器,这应该反过来使用 spinner.setSelection(pos) 触发 onItemSelected()?

【问题讨论】:

    标签: android spinner android-custom-view


    【解决方案1】:

    Events基本上是Activity实现的一个接口,通过点击Spinner的DropDown View的LinearLayout来接收回调。

    public class MyArrayAdapter extends BaseAdapter {
    
    String[] values;
    int CustomResource;
    Context context;
    Events events;
    
    public MyArrayAdapter(Context baseContext, int customspinnerview,
            String[] stringArray, Events events) {
        values = stringArray;
        context = baseContext;
        this.events = events;
        CustomResource = customspinnerview;
    
    }
    
    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return values.length;
    }
    
    @Override
    public Object getItem(int position) {
        if (position < values.length)
            return values[position];
        else {
            return null;
        }
    }
    
    
    @Override
    public View getView(final int position, final View convertView,
            ViewGroup parent) {
        View rowView = convertView;
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (rowView == null) {
            rowView = inflater.inflate(CustomResource, parent, false);
        }
        TextView textView = (TextView) rowView.findViewById(R.id.dropdown_text);
        textView.setText(values[position]);
        Button button = (Button) rowView.findViewById(R.id.Button_text);
        return rowView;
    }
    
    @Override
    public View getDropDownView(final int position, View convertView,
            ViewGroup parent) {
    
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowView = convertView;`enter code here`
        if (rowView == null) {
            rowView = inflater.inflate(CustomResource, parent, false);
    
        }
        final LinearLayout parentRelative = (LinearLayout) rowView
                .findViewById(R.id.parent);
        final TextView textView = (TextView) rowView
                .findViewById(R.id.dropdown_text);
        textView.setText(values[position]);
        Button button = (Button) rowView.findViewById(R.id.Button_text);
        rowView.setOnClickListener(new OnClickListener() {
    
            @Override
            public void onClick(View v) {
                events.onItemSelectedLister(
                        (AdapterView<?>) parentRelative.getParent(),
                        parentRelative, position, (long) 0);
    
            }
        });
        // Button buttonView = (Button)
        // rowView.findViewById(R.id.dropdown_button);
    
        return rowView;
    }
    

    Events 接口 它是 Activity 实现的接口,用于接收来自 Adapter 的回调。

    import android.view.View;
    import android.widget.AdapterView;
    
    public interface Events {
    
    public void onItemSelectedLister(AdapterView<?> parent, View view,
            int position, long id);
    }
    

    活动实施。

    onItemSelected Implementation 是您可以完成任务的地方.....

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import android.annotation.TargetApi;
    import android.app.Activity;
    import android.os.Build;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.Spinner;
    import com.example.adapter.MyArrayAdapter;
    
    public class MainActivity extends Activity implements Events {
    Spinner spinner;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        spinner = (Spinner) findViewById(R.id.spinner);
        spinner.setAdapter(new MyArrayAdapter(getBaseContext(),
                R.layout.customspinnerview, getResources().getStringArray(
                        R.array.values), this));
    }
    
    @Override
    public void onItemSelectedLister(AdapterView<?> parent, View view,
            final int position, long id) {
            //perform your Task.......
        Method method;
        try {
            method = Spinner.class.getDeclaredMethod("onDetachedFromWindow");
            method.setAccessible(true);
            try {
                method.invoke(spinner);
            } catch (IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        spinner.post(new Runnable() {
    
            @Override
            public void run() {
                spinner.setSelection(position);
                spinner.setSelected(true);
                ((MyArrayAdapter) spinner.getAdapter()).notifyDataSetChanged();
            }
        });
    
    }
    }
    

    setContentView 的活动 xml 文件

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.customspinner.MainActivity" >
    
    <Spinner
        android:id="@+id/spinner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </Spinner>
    
    </RelativeLayout>
    

    作为布局文件传递给适配器的 Spinner View。

    <LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#99000000"
    android:id="@+id/parent"
    android:orientation="horizontal">
    <TextView
        android:id="@+id/dropdown_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    
    <Button 
         android:id="@+id/Button_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="remove"/>
    
    </LinearLayout>
    

    代码运行良好 :)。我的代码运行良好。

    【讨论】:

    • 非常感谢 Shahroze。我确定您的代码可以正常工作,但是要实现看似非常简单的东西似乎很复杂?
    • 欢迎您。已使用动态方法来实现该功能。
    【解决方案2】:

    解决方法是在TextView和Button的布局中设置android:focusable="false"。

    <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/dropdown_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:focusable="false"
            android:singleLine="true" />
        <Button
            android:id="@+id/dropdown_button"
            android:layout_height="match_parent"
            android:layout_width="wrap_content"
            android:layout_alignParentRight="true"
            android:focusable="false"
            android:text="Remove"/>
    </RelativeLayout>
    

    或者也可以在代码中这样做:

    textView.setFocusable(false);
    buttonView.setFocusable(false);
    

    找到答案here。这是因为 Spinner 实现只允许视图中有一个可聚焦的项目。这就是我无法选择项目的原因。

    【讨论】:

    • 您是否在 getDropDownView 中定义了 OnClickListener 并且有效?在我的情况下,当我在 getDropDownView 添加任何 OnClickListener 时,单击后微调器视图不会关闭。
    • 这拯救了我的一天!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多