2014-01-23 64 views
4

我不知道爲什麼有一個ListView的layout_height =「WRAP_CONTENT」後,在列表的末尾弄亂紗廠。我通過不同的方式修復它下面。我希望有人能夠解釋這些行爲,或者指出我缺乏關於繪製views/ui事件的android知識。微調下拉繪圖屏幕列表視圖的頂部選擇項目

1)的問題在視覺上可以看到here

2)改變列表項屬性

android:descendantFocusability="afterDescendants" 

後,我得到更好的行爲,而是仍在繼續。它看起來像列表中的項目沒有收到事件,所以財產變化對我有意義。 Here is a video在更新該屬性後,紡紗工如何行爲。 除了當我實際選擇一個項目時,所有的工作都很好。

3)設置ListView的layout_height =「match_parent」之後,問題似乎選擇一個項目後走開。該視頻爲See here

的活動:

public class SelectorActivity extends Activity { 

public static final String TAG = SelectorActivity.class.getSimpleName(); 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    Log.v(TAG, "onCreate"); 
    setContentView(R.layout.activity_selector); 

    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

    ListView contents = (ListView) findViewById(R.id.list_view);  
    contents.addHeaderView(new TestView(this)); 
    contents.addFooterView(new View(this)); 
    SimpleBaseAdapter listAdapter = new SimpleBaseAdapter(this); 

    // LOW RANGE 
    LinearLayout lowRange = (LinearLayout) inflater.inflate(R.layout.list_item_edit, null); 
    TextView lowRangeText = (TextView) lowRange.findViewById(R.id.text); 
    EditText lowRangeEditText = (EditText) lowRange.findViewById(android.R.id.edit); 
    // HIGH RANGE 
    LinearLayout highRange = (LinearLayout) inflater.inflate(R.layout.list_item_edit, null); 
    TextView highRangeText = (TextView) highRange.findViewById(R.id.text); 
    EditText highRangeEditText = (EditText) highRange.findViewById(android.R.id.edit); 
    // UNITS 
    LinearLayout units = (LinearLayout) inflater.inflate(R.layout.list_item_units, null); 
    TextView unitsText = (TextView) units.findViewById(android.R.id.text1); 

    // SPINNERS 
    LinearLayout spinners = (LinearLayout) inflater.inflate(R.layout.list_item_spinners, null); 

    Spinner spinner1 = (Spinner) spinners.findViewById(R.id.spinner1); 
    Spinner spinner2 = (Spinner) spinners.findViewById(R.id.spinner2); 
    Spinner spinner3 = (Spinner) spinners.findViewById(R.id.spinner3); 
    DebugAdapterViewListeners.set(spinner1, "spinner1"); 

    // VIEW SETUP 
    lowRangeText.setText("text1"); 
    highRangeText.setText("text2"); 
    unitsText.setText("text3"); 
    // SPINNER SETUP 
    String[] massUnits1 = new String[]{"one","two"}; 
    String[] massUnits2 = new String[]{"three","four"}; 
    String[] timeUnits = new String[]{"five","six"}; 

    ArrayAdapter<String> adapt1 = new ArrayAdapter<String>(this, R.layout.spinner_list_item_centered); 
    ArrayAdapter<String> adapt2 = new ArrayAdapter<String>(this, R.layout.spinner_list_item_centered); 
    ArrayAdapter<String> adapt3 = new ArrayAdapter<String>(this, R.layout.spinner_list_item_centered); 
    adapt1.addAll(massUnits1); 
    adapt2.addAll(massUnits2); 
    adapt3.addAll(timeUnits); 
    spinner1.setAdapter(adapt1); 
    spinner2.setAdapter(adapt2); 
    spinner3.setAdapter(adapt3); 

    listAdapter.addView(lowRange); 
    listAdapter.addView(highRange); 
    listAdapter.addView(units); 
    listAdapter.addView(spinners); 

    contents.setAdapter(listAdapter); 
} 


@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.selector, menu); 
    return false; 
} 


} 

這裏是SimpleBaseAdapter類:

public class SimpleBaseAdapter extends BaseAdapter { 

private ArrayList<View> views; 
private Context context; 

public SimpleBaseAdapter(Context context) { 
    this.context = context; 
    this.views = new ArrayList<View>(); 
} 

public void addView(View view) { 
    this.views.add(view); 
} 

@Override 
public int getCount() { 
    return views.size(); 
} 

@Override 
public Object getItem(int position) { 
    View view = views.get(position); 
    if (view instanceof AbsListView) { 
     return ((AbsListView)view).getItemAtPosition(position); 
    } else if (view instanceof AbsSpinner) { 
     return ((AbsSpinner)view).getItemAtPosition(position); 
    } else { 
     return null; 
    } 
} 

@Override 
public long getItemId(int position) { 
    View view = views.get(position); 
    if (view instanceof AbsListView) { 
     return ((AbsListView)view).getItemIdAtPosition(position); 
    } else if (view instanceof AbsSpinner) { 
     return ((AbsSpinner)view).getItemIdAtPosition(position); 
    } else { 
     return 0; 
    } 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    return views.get(position); 
} 

} 

活動佈局:

<LinearLayout 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:background="@color/green_1" 
    android:orientation="vertical" 
    > 
    <ListView 
     android:id="@+id/list_view" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:headerDividersEnabled="true" 
     android:footerDividersEnabled="true"   
     android:dividerHeight="0.5sp" 
     android:divider="@color/black" 
     android:clipToPadding="false" 
     android:layout_marginTop="18sp" 
     android:layout_marginBottom="18sp" 
      /> 
</LinearLayout> 

編輯列表項的佈局:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="horizontal" 
    android:padding="@dimen/row_padding" 
     android:background="@android:color/white" 
    > 
    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/text" 
      android:layout_weight="50" 
     android:gravity="top" 
     android:textSize="@dimen/font_size_standard" 
     android:textColor="@drawable/selector_row_item_detail_text" 
     /> 
    <EditText 
      android:layout_width="0dip" 
     android:layout_height="wrap_content" 
     android:id="@android:id/edit" 
     android:layout_weight="50" 
     android:inputType="number" 
     android:gravity="right" 
     /> 
</LinearLayout> 

的微調行項目佈局:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:id="@+id/spinner_container" 
     android:orientation="horizontal" 
     android:background="@android:color/white" 
     android:paddingTop="@dimen/header_row_padding_vertical" 


     > 
      <Spinner 
       android:layout_width="0dip" 
       android:layout_height="wrap_content" 
       android:layout_weight="33" 
       android:id="@+id/spinner1" 
       android:gravity="center" 
       android:spinnerMode="dropdown" 
       /> 
      <Spinner 
       android:layout_width="0dip" 
       android:layout_height="wrap_content" 
       android:layout_weight="33" 
       android:id="@+id/spinner2" 
       android:gravity="center" 
       android:spinnerMode="dialog" 
       /> 
      <Spinner 
       android:layout_width="0dip" 
       android:layout_height="wrap_content" 
       android:layout_weight="33" 
       android:id="@+id/spinner3" 
       android:gravity="center" 
       android:spinnerMode="dialog" 
       /> 
     </LinearLayout> 

回答

1

您應該擴展SpinnerAdapter而非BaseAdapter。它具有getDropdownView()以及getView(),我相信它在內部處理一些特殊情況。我在android 4.2上以類似的佈局擴展這個適配器,我沒有看到你有問題。

我會哈扎德猜測,在getDropdownView()如何處理連接視圖到根將佔這種差異,但我還沒有研究的代碼來檢查這個

+0

好的謝謝。我會試一試該適配器併發布結果。 – ryancwarren

+0

這不適合我;你有什麼在你的impl getDropdownView?謝謝。 – ryancwarren

+0

我現在在工作,當我回家時,我會與你分享,同時也許你可以使用微調適配器而不是基礎適配器更新你的問題? –

4

你是問題的差異面對的是Spinner的基本行爲,所以需要修改Spinner。這是最初ie的微調代碼。默認情況下,可視化爲「選擇項目」(如果在.xml中聲明的提示類似android:prompt="@string/Select Item")&,則下拉視圖與原始微調控件的大小相同。此修改微調器的限制是,如果項目爲空,它不會顯示提示。

做一個在副本命名爲NoDefaultSpinner.java &新類粘貼此代碼

public class NoDefaultSpinner extends Spinner { 

    public NoDefaultSpinner(Context context) { 
     super(context); 
    } 

    public NoDefaultSpinner(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public NoDefaultSpinner(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    @Override 
    public void setAdapter(SpinnerAdapter orig) { 
     final SpinnerAdapter adapter = newProxy(orig); 

     super.setAdapter(adapter); 

     try { 
      final Method m = AdapterView.class.getDeclaredMethod(
           "setNextSelectedPositionInt",int.class); 
      m.setAccessible(true); 
      m.invoke(this,-1); 

      final Method n = AdapterView.class.getDeclaredMethod(
           "setSelectedPositionInt",int.class); 
      n.setAccessible(true); 
      n.invoke(this,-1); 
     } 
     catch(Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

    protected SpinnerAdapter newProxy(SpinnerAdapter obj) { 
     return (SpinnerAdapter) java.lang.reflect.Proxy.newProxyInstance(
       obj.getClass().getClassLoader(), 
       new Class[]{SpinnerAdapter.class}, 
       new SpinnerAdapterProxy(obj)); 
    } 



    /** 
    * Intercepts getView() to display the prompt if position < 0 
    */ 
    protected class SpinnerAdapterProxy implements InvocationHandler { 

     protected SpinnerAdapter obj; 
     protected Method getView; 


     protected SpinnerAdapterProxy(SpinnerAdapter obj) { 
      this.obj = obj; 
      try { 
       this.getView = SpinnerAdapter.class.getMethod(
           "getView",int.class,View.class,ViewGroup.class); 
      } 
      catch(Exception e) { 
       throw new RuntimeException(e); 
      } 
     } 

     public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { 
      try { 
       return m.equals(getView) && 
         (Integer)(args[0])<0 ? 
         getView((Integer)args[0],(View)args[1],(ViewGroup)args[2]) : 
         m.invoke(obj, args); 
      } 
      catch (InvocationTargetException e) { 
       throw e.getTargetException(); 
      } 
      catch (Exception e) { 
       throw new RuntimeException(e); 
      } 
     } 

     protected View getView(int position, View convertView, ViewGroup parent) 
      throws IllegalAccessException { 

      if(position<0) { 
       final TextView v = 
        (TextView) ((LayoutInflater)getContext().getSystemService(
        Context.LAYOUT_INFLATER_SERVICE)).inflate(
         android.R.layout.simple_spinner_item,parent,false); 
       v.setText(getPrompt()); 
       return v; 
      } 
      return obj.getView(position,convertView,parent); 
     } 
    } 
} 

在微調行項目佈局改變微調的類型<com.example.appname.NoDefaultSpinner這樣

 <com.example.appname.NoDefaultSpinner 
      android:layout_width="0dip" 
      android:layout_height="wrap_content" 
      android:layout_weight="33" 
      android:id="@+id/spinner1" 
      android:gravity="center" 
      android:spinnerMode="dropdown" 
      /> 
     <com.example.appname.NoDefaultSpinner 
      android:layout_width="0dip" 
      android:layout_height="wrap_content" 
      android:layout_weight="33" 
      android:id="@+id/spinner2" 
      android:gravity="center" 
      android:spinnerMode="dialog" 
      /> 
     <com.example.appname.NoDefaultSpinner 
      android:layout_width="0dip" 
      android:layout_height="wrap_content" 
      android:layout_weight="33" 
      android:id="@+id/spinner3" 
      android:gravity="center" 
      android:spinnerMode="dialog" 
      /> 

的活動:更改Spinner類型爲NoDefaultSpinner這樣的

public class SelectorActivity extends Activity { 

public static final String TAG = SelectorActivity.class.getSimpleName(); 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
Log.v(TAG, "onCreate"); 
setContentView(R.layout.activity_selector); 

LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

ListView contents = (ListView) findViewById(R.id.list_view);  
contents.addHeaderView(new TestView(this)); 
contents.addFooterView(new View(this)); 
SimpleBaseAdapter listAdapter = new SimpleBaseAdapter(this); 

// LOW RANGE 
LinearLayout lowRange = (LinearLayout) inflater.inflate(R.layout.list_item_edit, null); 
TextView lowRangeText = (TextView) lowRange.findViewById(R.id.text); 
EditText lowRangeEditText = (EditText) lowRange.findViewById(android.R.id.edit); 
// HIGH RANGE 
LinearLayout highRange = (LinearLayout) inflater.inflate(R.layout.list_item_edit, null); 
TextView highRangeText = (TextView) highRange.findViewById(R.id.text); 
EditText highRangeEditText = (EditText) highRange.findViewById(android.R.id.edit); 
// UNITS 
LinearLayout units = (LinearLayout) inflater.inflate(R.layout.list_item_units, null); 
TextView unitsText = (TextView) units.findViewById(android.R.id.text1); 

// SPINNERS 
LinearLayout spinners = (LinearLayout) inflater.inflate(R.layout.list_item_spinners, null); 

NoDefaultSpinner spinner1 = (NoDefaultSpinner) spinners.findViewById(R.id.spinner1); 
NoDefaultSpinner spinner2 = (NoDefaultSpinner) spinners.findViewById(R.id.spinner2); 
NoDefaultSpinner spinner3 = (NoDefaultSpinner) spinners.findViewById(R.id.spinner3); 
DebugAdapterViewListeners.set(spinner1, "spinner1"); 

// VIEW SETUP 
lowRangeText.setText("text1"); 
highRangeText.setText("text2"); 
unitsText.setText("text3"); 
// SPINNER SETUP 
String[] massUnits1 = new String[]{"one","two"}; 
String[] massUnits2 = new String[]{"three","four"}; 
String[] timeUnits = new String[]{"five","six"}; 

ArrayAdapter<String> adapt1 = new ArrayAdapter<String>(this, R.layout.spinner_list_item_centered); 
ArrayAdapter<String> adapt2 = new ArrayAdapter<String>(this, R.layout.spinner_list_item_centered); 
ArrayAdapter<String> adapt3 = new ArrayAdapter<String>(this, R.layout.spinner_list_item_centered); 
adapt1.addAll(massUnits1); 
adapt2.addAll(massUnits2); 
adapt3.addAll(timeUnits); 
spinner1.setAdapter(adapt1); 
spinner2.setAdapter(adapt2); 
spinner3.setAdapter(adapt3); 

listAdapter.addView(lowRange); 
listAdapter.addView(highRange); 
listAdapter.addView(units); 
listAdapter.addView(spinners); 

contents.setAdapter(listAdapter); 
} 


@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
getMenuInflater().inflate(R.menu.selector, menu); 
return false; 
} 

此解決方案依靠反射將AdapterView.setNextSelectedPositionInt()AdapterView.setSelectedPositionInt(),&在API 4上成功運行到API 19.

+2

你的解決方案似乎有效,但我不明白爲什麼它是必要的,是什麼導致了問題。你能否進一步解釋? – ryancwarren

+0

我同意。在獎勵獎勵之前,解釋會有所幫助。你能解釋爲什麼這個解決方案正在工作嗎?謝謝! – docksteaderluke

+0

@ryancwarren我編輯&解釋furthur :) –

相關問題