自定义下拉视图的Spinner未触发onItemSelected()函数

4
我有一个Spinner,使用自定义适配器,其中重写了getDropDownView()方法。自定义下拉视图中的每个项目由TextView和Button组成。
但是,当我运行代码时,Spinner下拉项显示正常,但单击它们无效。 Spinner下拉仍保持打开状态,且未触发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 = (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()方法?

2个回答

3
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 Interface是一种接口,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 实现是您可以完成任务的地方......

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的Activity 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>

在Adapter中作为布局文件传递的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。我相信你的代码是可行的,但看起来为了实现一些看似很简单的东西而需要处理很多复杂性? - MickeyR
欢迎,为了实现该功能采用了动态方法。 - Shahroze Shahid Khan

3
解决方案是在 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);

在这里找到了答案这个方法有效是因为Spinner实现只允许视图中有一个可聚焦的项目。这就是为什么我无法选择该项的原因。


你在getDropDownView中定义了OnClickListener并且它起作用了吗?在我的情况下,当我在getDropDownView中添加任何OnClickListener时,点击后spinner视图不会关闭。 - Mahdi
这挽救了我的一天!! - OwlR

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