2017-01-17 2 views
9

У меня есть экран настроек с помощью «пользовательского макета»:Предпочтения экрана пользовательский макет работает только со вторым щелчком

android:layout="@layout/currencycodes" 

Этой проблема является она не вызвать расположение на первую попытку. Как вы видите из анимированного gif ниже, мне нужно отступить и повторить попытку еще раз, чтобы макет подошел. Теперь почему?

enter image description here

preferences.xml

<?xml version="1.0" encoding="utf-8"?> 
<PreferenceScreen 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:key="application_preferences"> 
    <PreferenceCategory> 
     <PreferenceScreen 
       android:key="url_settings" 
       android:title="@string/url_settings" 
       android:summary="@string/summary_url_settings"> 
     </PreferenceScreen> 

     <PreferenceScreen 
       android:key="currency_codes" 
       android:title="@string/left_handed" 
       android:summary="@string/summary_left_handed"> 
      <Preference 
        android:key="currency_exchanges" 
        android:layout="@layout/currencycodes"/> 
     </PreferenceScreen> 
     <EditTextPreference 
       android:key="url_exchange_rate" 
       android:title="@string/url_exchange_rate_settings" 
       android:summary="@string/summary_url_exchange_rate" 
       android:enabled = "false"/> 
    </PreferenceCategory> 
</PreferenceScreen> 

Ниже пользовательский макет используется. Он содержит GridView.

currencycodes.xml

<?xml version="1.0" encoding="utf-8"?> 
<android.support.constraint.ConstraintLayout 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:app="http://schemas.android.com/apk/res-auto" 
     xmlns:tools="http://schemas.android.com/tools" 
     android:id="@+id/activity_main" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:focusable="true" 
     android:focusableInTouchMode="true" 
     tools:context=".MainActivity"> 

    <GridView 
      android:layout_width="328dp" 
      android:layout_height="479dp" 
      android:layout_marginTop="16dp" 
      app:layout_constraintTop_toTopOf="parent" android:layout_marginStart="16dp" 
      app:layout_constraintLeft_toLeftOf="parent" android:layout_marginEnd="16dp" 
      app:layout_constraintRight_toRightOf="parent" 
      app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="16dp" 
      android:id="@+id/grdExchanges" android:scrollbars="horizontal|vertical" 
      android:smoothScrollbar="true" tools:textAlignment="center" 
      android:verticalScrollbarPosition="defaultPosition"/> 
</android.support.constraint.ConstraintLayout> 
+0

добавьте Java, как well –

ответ

1

Я придумал обходное решение. Я заметил, когда надувания макета в LayoutInflater.java, статический HashMap используется для сбора объектов вида:

private static final HashMap<String, Constructor<? extends View>> sConstructorMap 

То, что происходит в том, что первый клик вызывает LayoutInflater, но это первый щелчок только добавляет GridView вида в статический hashmap. Вы увидите, что с первым щелчком, команда, sConstructorMap.get(name), возвращает только нуль:

public final View createView(String name, String prefix, AttributeSet attrs) 
     throws ClassNotFoundException, InflateException { 

    Constructor<? extends View> constructor = sConstructorMap.get(name); 

    Class<? extends View> clazz = null; 

     try { 

      if (constructor == null) { 

В LayoutInflater, переменная, mPrivateFactory, фактически ваша основная деятельность. Именно там мой gridview будет инициализирован в файле mPrivateFactory.onCreateView(). Однако при первом щелчке mPrivateFactory.onCreateView() возвращает значение null, потому что статический хэш-файл не имеет вида gridview .... Это далее в командной строке, onCreateView(parent, name, attrs);, где он, наконец, добавил:

if (view == null && mPrivateFactory != null) { 
     view = mPrivateFactory.onCreateView(parent, name, context, attrs); 
    } 

    if (view == null) { 
     final Object lastContext = mConstructorArgs[0]; 
     mConstructorArgs[0] = context; 
     try { 
      if (-1 == name.indexOf('.')) { 
       view = onCreateView(parent, name, attrs); <-- ADD TO STATIC HASHMAP 
      } else { 
       view = createView(name, null, attrs); 
      } 
     } finally { 
      mConstructorArgs[0] = lastContext; 
     } 
    } 

Так, пока я не придумал более элегантным решением, я просто вызвать метод, onCreateView(parent), дважды в первый раз, особое предпочтение щелкнуло на. Первый вызов добавляет GridView к статическому HashMap, то второй вызов затем конкретизирует вид макета (опять же), но на этот раз, инициализирует GridView в моем собственном методе onCreateView Activity, в mPrivateFactory.onCreateView():

protected View onCreateView(ViewGroup parent) { 

View layout = super.onCreateView(parent); 

if(firstCall){ 

    firstCall = false; 

    layout = super.onCreateView(parent); 
} 

return layout; 
} 
1

попробуйте изменить if заявление от

(!mFragMngr.popBackStackImmediate(fragName, 0) 
       && mFragMngr.findFragmentByTag(fragName) == null) 

в

(mFragMngr.findFragmentByTag(fragName) == null) 
+0

Это просто определяет, была ли нажата кнопка настройки передачи, или фрагмент уже отображается. Ничего общего с этой проблемой. – Drawn

2

Ну, прежде всего вы должны понять, как PreferenceScreen Works ??

Из [документации Android] [1]:

Когда он появляется в другой иерархии предпочтений, показано и служит в качестве шлюза к другому экрану предпочтений (либо , показывающий другой экран предпочтений как Диалог или через startActivity (android.content.Intent) из getIntent()). На этом экране предпочтений не отображаются дети . Этот экран предпочтений показан на экране . Вместо этого на экране будет отображаться при выборе этого предпочтения.

В простых словах,

Рамки предпочтения ручки, показывая эти другие экраны из иерархии предпочтений. Этот тег PreferenceScreen служит в качестве разрыва экрана (аналогично разрыву страницы в текстовой обработке). Подобно другим типам предпочтений, мы назначаем ключ здесь, чтобы он мог сохранять и восстанавливать свое состояние экземпляра.

В вашем случае, что на самом деле происходит, «application_preferences» будет использоваться в качестве корня иерархии и дается в первом экране PreferenceActivity.The покажет предпочтения «Url_Setting» и "коды валют ». В «Коды валют» является «second_preferencescreen» и при нажатии появится еще один экран настроек, который «Обмен валюты» (как это предпочтения как дети «second_preferencescreen» Тег т.е. Коды валют).

Так что, почему его не показываете на первый нажмите .... но на второй клик надеюсь, что вы получили , как работает предпочтение Screen ...

Если у вас есть какие-либо сомнения ... дайте мне знать. .. https://developer.android.com/reference/android/preference/PreferenceScreen.html

+0

Вы читаете документацию PreferenceScreen без учета этой конкретной проблемы. «Итак, почему он не показывает первый клик ...» - вы ничего не сказали, что объясняет, почему его не показывают при первом нажатии. «Валютные коды» - это не «второй_режим экрана», а третий. Второй - «url_settings», и он отлично работает. – Drawn

+0

@drawn код валюты - второй экран предпочтения. В соответствии с вашим кодом, который имеет другой ключ предпочтения в нем, который является обменом валюты, см. Вы упомянули. Предположите, что это не экран предпочтений. Для обмена валюты. Я процитировал это из документов, чтобы вы знали, что говорят официальные документы о иерархии предпочтений. .It всегда о иерархии предпочтений и screen.Root иерархии не учитывается как первый, который является вашим application_preference.given для деятельности предпочтения. Надеюсь, у меня есть моя точка. Все дело в иерархии предпочтений. Индексирование. Внутри в андроиде. Где твоя проблема? ??? – PN10

+0

URL_settings будет работать нормально, так как это первый экран предпочтений, но кодами валют является второй экран предпочтений, который имеет другое предпочтение. Для этого screen.iecurrency exchange ... См. Порядок экрана настроек ... Здесь ... – PN10

Смежные вопросы