我在表单上的spinners
很少。当我点击它们中的任何一个时,它会打开并显示选项。当我点击任何其他spinner
时,它会关闭打开的spinner
,但我需要再次点击所需的spinner
才能打开它。
我想第一次点击第二个微调器,这样我就可以关闭第一个打开的微调器,然后打开单击的微调器。
我看过关于在外面的任何点击上关闭微调器的帖子,但这还不够,因为我仍然不知道所需的微调器被点击(第二个微调器的onclick()
没有被触发)。 / p>
答案 0 :(得分:1)
我有点忙于编写并提供一些代码,但是从this这样的链接获得帮助可以获得一些代码。所以这是我的想法。首先在创建视图时,获取微调器的坐标,例如微调器A,B和C.还要编写一个函数(例如foo(...)
),它返回点击点的坐标但不是消耗它。然后注册A,B和C onItemSelectedListeners
并在onNothingSelected
检查点击点是否在旋转器的其他两个区域(使用您之前写的foo(...)
)。这样你就可以得到你想要的东西。对不起,我既忙又懒,但这很有效。我希望我帮助过你。
更新(接收触摸):
好吧,我尝试了几种方法,说实话其中没有一种方法有效,即使让活动拦截触摸事件没有帮助,所以我猜开启微调器的情况就像弹出窗口,在这种情况下,一个解决方案来到我的心。
您需要在所有视图的顶部放置一个透明图层来拦截触摸,但它应该像锁定屏幕中使用的那样,这样就不会有其他对话框或视图。如果您已经编写了锁屏应用程序或尝试过这样做,您就知道该怎么做了。
然而,对于这种情况,许可将是矫枉过正的,除非你找到另一种和平的方式,否则我不建议你去做。
答案 1 :(得分:1)
这是一个自定义微调器,可以完全满足您的需要,
<强> PopupActionSpinner.java 强>
package com.selva.widget;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListPopupWindow;
import android.widget.PopupWindow;
import android.widget.Spinner;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class PopupActionSpinner extends Spinner {
private static final String M_POPUP = "mPopup";
private static final String DROPDOWN_POPUP = "DropdownPopup";
private static final String IS_SHOWING = "isShowing";
private static final String DIALOG_POPUP = "DialogPopup";
private static final int MODE_UNKNOWN = -1;
private PopupTouchInterceptor popupTouchInterceptor;
private Field mFieldSpinnerPopup = null;
private PopupActionSpinner[] mPopupActionSpinnersArr = null;
/**
* Construct a new spinner with the given context's theme and the supplied attribute set.
*
* @param context The Context the view is running in, through which it can
* access the current theme, resources, etc.
* @param attrs The attributes of the XML tag that is inflating the view.
*/
public PopupActionSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* Define your own Interface to control what happens when the Spinner dropdown popup is open.
* @param mpopupTouchInterceptor
*/
public void setPopupTouchInterceptor(PopupTouchInterceptor mpopupTouchInterceptor,
PopupActionSpinner[] allSpinners )
{
this.popupTouchInterceptor = mpopupTouchInterceptor;
this.mPopupActionSpinnersArr = allSpinners;
}
@Override
public boolean performClick() {
boolean handled = true;
try {
handled = super.performClick();
// reflecting Spinner.mPopup field
if (isFieldSpinnerPopupNull()) {
mFieldSpinnerPopup = this.getClass().getSuperclass().getDeclaredField(M_POPUP);
}
// disable access checks to Spinner.mPopup
mFieldSpinnerPopup.setAccessible(true);
// get value of mPopup field
Object spinnerPopup = mFieldSpinnerPopup.get(this);
// reflecting SpinnerPopup.isShowing()
Method isShowing = mFieldSpinnerPopup.getType()
.getDeclaredMethod(IS_SHOWING, (Class[]) null);
// calling Spinner.mPopup.isShowing()
boolean isShowingResult = (boolean) isShowing.invoke(spinnerPopup, (Object[]) null);
if (isShowingResult) {
// check if mFieldSpinnerPopup is a dialog popup
if (getSpinnerMode() == MODE_DIALOG) {
//Do Nothing
} else if (getSpinnerMode() == MODE_DROPDOWN) {
// reflecting Spinner.mPopup.mPopup
Field fieldPopupWindow = ListPopupWindow.class.getDeclaredField(M_POPUP);
fieldPopupWindow.setAccessible(true);
((PopupWindow) fieldPopupWindow.get(spinnerPopup)).setTouchInterceptor(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
if(!isViewInBounds(view,event.getRawX(),event.getRawY())) {
for (View spinnerView : mPopupActionSpinnersArr)
if (isPointInsideView(event.getRawX(), event.getRawY(), spinnerView)) {
popupTouchInterceptor.onTouchIntercepted(spinnerView);
break;
}
}
break;
}
}
return false;
}
});
fieldPopupWindow.setAccessible(false);
}
}
// enable access checks to Spinner.mPopup
mFieldSpinnerPopup.setAccessible(false);
} catch (Exception exception) {
}
return handled;
}
public static boolean isPointInsideView(float x, float y, View view){
int location[] = new int[2];
view.getLocationOnScreen(location);
int viewX = location[0];
int viewY = location[1];
//point is inside view bounds
if(( x > viewX && x < (viewX + view.getWidth())) &&
( y > viewY && y < (viewY + view.getHeight()))){
return true;
} else {
return false;
}
}
private boolean isViewInBounds(View view, float x, float y) {
Rect outRect = new Rect();
int[] location = new int[2];
view.getDrawingRect(outRect);
view.getLocationOnScreen(location);
outRect.offset(location[0], location[1]);
return outRect.contains((int)x, (int)y);
}
/**
* Returns a constant describing how the user selects choices from the spinner.
*
* @return the choosing mode of this <code>{@link Spinner}</code>
*/
public int getSpinnerMode() {
int result = MODE_UNKNOWN;
try {
// reflecting Spinner.mPopup field
if (isFieldSpinnerPopupNull()) {
mFieldSpinnerPopup = this.getClass().getSuperclass().getDeclaredField(M_POPUP);
}
// get Spinner.DropdownPopup class name
mFieldSpinnerPopup.setAccessible(true);
String spinnerPopupClassName = mFieldSpinnerPopup.get(this).getClass().getSimpleName();
mFieldSpinnerPopup.setAccessible(false);
switch (spinnerPopupClassName) {
case DIALOG_POPUP:
result = MODE_DIALOG;
break;
case DROPDOWN_POPUP:
result = MODE_DROPDOWN;
break;
default:
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
public boolean isFieldSpinnerPopupNull() {
return mFieldSpinnerPopup == null;
}
@Override
public int getId() {
return super.getId();
}
}
我使用Java Reflection访问弹出窗口并覆盖了TouchInteceptor。通过这种方式,您将能够控制活动中的触摸事件,反过来您可以打开下一个微调器而无需单击两次。
为了弄清楚,从Github克隆我的样本并运行相同的。如果您有任何疑问,请告诉我。
答案 2 :(得分:1)
无论您要为旋转器实现setOnItemClickListener的位置,都应编写此行代码:
spinner.requestFocusFromTouch();
这将告诉微调器一键调用并显示项目列表。
答案 3 :(得分:0)
尝试使用此一行代码打开您的微调器而不点击它
((Spinner) findViewById(R.id.selected_area_spinner)).performClick();
但是在初始化微调器之后使用此代码
答案 4 :(得分:0)
尝试使用此代码帮助您
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
/**
* Created by riyazudinp on 8/11/2016.
*/
public class MyActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener, View.OnClickListener {
private String dataForSpinnerOne[] = {"A", "B", "C", "D", "E"};
private String dataForSpinnerTwo[] = {"F", "G", "H", "I", "J"};
private String dataForSpinnerThree[] = {"K", "L", "M", "N", "O"};
private Spinner spinnerOne;
private Spinner spinnerTwo;
private Spinner spinnerThree;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
spinnerOne = (Spinner) findViewById(R.id.spinner1);
spinnerTwo = (Spinner) findViewById(R.id.spinner2);
spinnerThree = (Spinner) findViewById(R.id.spinner3);
ArrayAdapter<String> adapter1 = new ArrayAdapter<>(MyActivity.this, android.R.layout.simple_list_item_1, dataForSpinnerOne);
ArrayAdapter<String> adapter2 = new ArrayAdapter<>(MyActivity.this, android.R.layout.simple_list_item_1, dataForSpinnerTwo);
ArrayAdapter<String> adapter3 = new ArrayAdapter<>(MyActivity.this, android.R.layout.simple_list_item_1, dataForSpinnerThree);
spinnerOne.setAdapter(adapter1);
spinnerTwo.setAdapter(adapter2);
spinnerThree.setAdapter(adapter3);
spinnerOne.setOnItemSelectedListener(this);
spinnerTwo.setOnItemSelectedListener(this);
spinnerThree.setOnItemSelectedListener(this);
spinnerOne.setOnClickListener(this);
spinnerTwo.setOnClickListener(this);
spinnerThree.setOnClickListener(this);
}
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
if (view == spinnerOne) {
//Spinner One Clicked
//add your code when spinner iten selected
}
if (view == spinnerTwo) {
//Spinner Two Clicked
//add your code when spinner iten selected
}
if (view == spinnerThree) {
//Spinner Three Clicked
//add your code when spinner iten selected
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
@Override
public void onClick(View view) {
if (view == spinnerOne) {
spinnerOne.performClick();
spinnerTwo.performClick();
spinnerThree.performClick();
}
if (view == spinnerTwo) {
spinnerOne.performClick();
spinnerTwo.performClick();
spinnerThree.performClick();
}
if (view == spinnerThree) {
spinnerOne.performClick();
spinnerTwo.performClick();
spinnerThree.performClick();
}
}
}
答案 5 :(得分:0)
anotherSpinner.setSelection(open_item_index);
答案 6 :(得分:0)
这几乎是不可能的。
Spinner -> AbsSpinner -> AdapterView<SpinnerAdapter> -> ViewGroup -> View
来自Spinner.Java
/**
* <p>A spinner does not support item click events. Calling this method
* will raise an exception.</p>
* <p>Instead use {@link AdapterView#setOnItemSelectedListener}.
*
* @param l this listener will be ignored
*/
我们无法访问点击事件。
OnClickListener uses public interface DialogInterface.
如果这个“功能”让你感到烦恼,我建议最好使用弹出式菜单而不是Spinner。
@zvi @Erfan Mowlaei似乎没有发布任何代码。这是我对他的想法的想法: ViewTreeObserver vto1 = spinnerOne.getViewTreeObserver();
vto1.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
if( !spinnerOne.getViewTreeObserver().isAlive() )
{
Log.e(TAG,"OnGlobalLayoutListener: ***NOT alive***");
// only need to calculate once, so remove listener
// viewToMeasure.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}else
{
Log.e(TAG,"OnGlobalLayoutListener: ***alive***");
/*when you post a message to a View,
the messages will only be delivered after
the View has been fully initialized (including being measured)*/
spinnerOne .post(new Runnable()
{
@Override
public void run()
{
Log.e(TAG,"OnGlobalLayoutListener: ***run test***");
// safe to get height and width here
spinnerTwo.setSelected(false);
spinnerThree.setSelected(false);
spinnerOne.performClick();
// LayerDrawable ld = (LayerDrawable)spinnerOne.getBackground();//cast problem
// ld.setLayerInset(1, 0, spinnerOne.getHeight() / 2, 0, 0);
}
});
}
}
});
注意:强> 正如我所说,这些方法都不起作用,因为事件是在运行时库中生成和使用的。他们从未暴露。
不工作的其他事项:
spinnerOne.setOnFocusChangeListener(new OnFocusChangeListener()
{
@Override
public void onFocusChange(View v, boolean hasFocus)
{
if(hasFocus)
{
spinnerOne.performClick();
Log.v(TAG, "onFocusChange spinnerOne GOT the focus");
Toast.makeText(getApplicationContext(), "spinnerOne got the focus", Toast.LENGTH_SHORT).show();
}else
{
Log.v(TAG, "onFocusChange spinnerOne LOST the focus");
Toast.makeText(getApplicationContext(), "spinnerOne lost the focus", Toast.LENGTH_SHORT).show();
}
}
});
每次执行“Zvi机动”时,您的问题确实会在logcat中引发一个条目:
08-14 01:19:55.575: W/InputEventReceiver(8676):
Attempted to finish an input event but
the input event receiver has already been disposed.
我对解决这个问题并不抱太大希望。