如何在另一个微调器打开时单击打开微调器

我在表格上的spinners很少。 当我点击它们中的任何一个时,它会打开并显示选项。 当我点击任何其他spinner它会关闭打开的spinner但是我需要再次单击所需的spinner以打开它。

我想抓住第二个微调器上的第一个单击,这样我就可以关闭第一个打开的微调器,然后打开单击的微调器。

我看到关于在外面的任何点击上关闭微调器的post,但这还不够,因为我仍然不知道所需的微调器被点击(第二个微调器的onclick()没有被触发)。

我有点忙着编写并给你一些代码,但是从这样的链接获得帮助你可以得到一些代码片段。 所以这是我的想法。 首先在创建视图时,获取微调器的坐标,例如微调器A,B和C.还要编写一个函数(例如foo(...) ),它返回单击点的坐标但不消耗它 。 然后在onNothingSelected注册A,B和C,并在onNothingSelected检查点击点是否在微调器的其他两个区域(使用你之前写的foo(...) )。 这样你就可以得到你想要的东西。 对不起,我既忙又懒,但这很有效。 我希望我帮助过你。

更新(接收触摸):

好吧,我尝试了几种方法,说实话其中没有一种方法有效,即使让活动拦截触摸事件也无济于事,所以我猜开启微调器的情况就像popup窗口一样,在这种情况下我想到了一个解决方案。

您需要在所有视图的顶部放置一个透明图层来拦截触摸,但它应该像锁定屏幕中使用的那样,这样就不会有其他对话框或视图。 如果您已经编写了锁屏应用程序或试图这样做,您就知道该怎么做了。

然而,对于这样的情况,许可将是矫枉过正的,除非你find另一种和平的方式,否则我不建议你去做。

这是一个自定义微调器,它可以完全满足您的需求,

PopUpActionspinner Github

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 {@link Spinner} */ 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来访问popup窗口并覆盖TouchInteceptor。 通过这种方式,您将能够控制活动中的触摸事件,反过来您可以打开下一个微调器而无需单击两次。

为了获得一个清晰的想法,从Github克隆我的样本并运行相同的。 如果您有任何疑问,请告诉我。

试试这一行代码打开你的微调器而不点击它

  ((Spinner) findViewById(R.id.selected_area_spinner)).performClick(); 

但是在初始化微调器后使用此代码

试试这段代码可以帮到你

 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 adapter1 = new ArrayAdapter<>(MyActivity.this, android.R.layout.simple_list_item_1, dataForSpinnerOne); ArrayAdapter adapter2 = new ArrayAdapter<>(MyActivity.this, android.R.layout.simple_list_item_1, dataForSpinnerTwo); ArrayAdapter 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(); } } } 

anotherSpinner.setSelection(open_item_index);

这几乎是不可能的。

Spinner类层次结构

 Spinner -> AbsSpinner -> AdapterView -> ViewGroup -> View 

来自Spinner.Java

 /** * 

A spinner does not support item click events. Calling this method * will raise an exception.

*

Instead use {@link AdapterView#setOnItemSelectedListener}. * * @param l this listener will be ignored */

我们无权访问click事件

 OnClickListener uses public interface DialogInterface. 

我可以建议的最好是使用popup菜单而不是Spinner,如果这个“function”让你烦恼的话。

@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. 

我对解决问题并不抱太大希望。