2016-12-06 2 views
7

У меня есть андроид дизайн макета, в котором У меня есть AppBar макет, который будет содержать Toolbar и еще один LinearLayout дизайн круга Drawable в TextView. который находится на одной высоте. Так что, когда я пытаюсь получить Toolbar или AppBar высоты/ширины, что возвращается только 0.по уходу за детьми Просмотров занимает слишком много времени, чтобы нарисовать на экране

activity_main.xml:

<android.support.design.widget.AppBarLayout 
     android:id="@+id/app_bar" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 
     app:layout_behavior="@string/appbar_scrolling_view_behavior"> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="?actionBarSize" 
      android:background="@color/colorPrimary" 
      app:layout_scrollFlags="enterAlways" /> 
     <LinearLayout 
      android:layout_width="match_parent" 
      android:layout_height="?actionBarSize" 
      android:layout_gravity="center_horizontal" 
      android:background="@color/colorPrimary" 
      android:orientation="horizontal" 
      app:layout_scrollFlags="enterAlways"> 

      <LinearLayout 
       android:layout_width="0dp" 
       android:layout_height="match_parent" 
       android:layout_gravity="center_horizontal" 
       android:layout_marginLeft="2dp" 
       android:layout_weight="1" 
       android:orientation="horizontal"> 

       <TextView 
        android:id="@+id/marked_questions" 
        style="@style/textview_summary_omr_toolbar_count" 
        android:background="@drawable/bg_percentage_default" 
        android:text="18" /> 

       <TextView 
        style="@style/textview_heading_summary_omr_toolbar" 
        android:text="Marked" /> 
      </LinearLayout> 

      <LinearLayout 
       android:layout_width="0dp" 
       android:layout_height="match_parent" 
       android:layout_gravity="center_horizontal" 
       android:layout_marginLeft="2dp" 
       android:layout_weight="1" 
       android:orientation="horizontal"> 

       <TextView 
        android:id="@+id/correct" 
        style="@style/textview_summary_omr_toolbar_count" 
        android:background="@drawable/bg_percentage_6" 
        android:text="18" 

        /> 

       <TextView 
        style="@style/textview_heading_summary_omr_toolbar" 
        android:text="Correct" /> 
      </LinearLayout> 

      <LinearLayout 
       android:layout_width="0dp" 
       android:layout_height="match_parent" 
       android:layout_gravity="center_horizontal" 
       android:layout_marginLeft="2dp" 
       android:layout_weight="1" 
       android:orientation="horizontal"> 

       <TextView 
        android:id="@+id/wrong" 
        style="@style/textview_summary_omr_toolbar_count" 
        android:background="@drawable/bg_percentage_wrong" 
        android:text="18" /> 

       <TextView 
        style="@style/textview_heading_summary_omr_toolbar" 
        android:text="Wrong" /> 
      </LinearLayout> 


      <LinearLayout 
       android:layout_width="0dp" 
       android:layout_height="match_parent" 
       android:layout_gravity="center_horizontal" 
       android:layout_marginLeft="2dp" 
       android:layout_weight="1" 
       android:orientation="horizontal"> 

       <TextView 
        android:id="@+id/conflicts" 
        style="@style/textview_summary_omr_toolbar_count" 
        android:background="@drawable/bg_percentage_3" 
        android:text="0" /> 

       <TextView 
        style="@style/textview_heading_summary_omr_toolbar" 
        android:text="Conflicts" /> 
      </LinearLayout> 

      <LinearLayout 
       android:layout_width="0dp" 
       android:layout_height="match_parent" 
       android:layout_gravity="center_horizontal" 
       android:layout_marginLeft="2dp" 
       android:layout_weight="1" 
       android:orientation="horizontal"> 

       <TextView 
        style="@style/textview_summary_omr_toolbar_count" 
        android:text="Score:" 
        android:textColor="@android:color/white" /> 

       <TextView 
        android:id="@+id/marks_scored" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_gravity="center_vertical" 
        android:gravity="center" 
        android:text="18/30" 
        android:textColor="@android:color/white" 
        android:textSize="18sp" /> 

      </LinearLayout> 


     </LinearLayout> 
    </android.support.design.widget.AppBarLayout> 
</android.support.design.widget.CoordinatorLayout> 

MainActivity.java: Здесь я инициализация Toolbar и AppBar и попытайтесь напечатать ширину и высоту как в журналах, так и возвращающих мне ноль.

public class MainActivity extends AppCompatActivity { 
    private Toolbar toolbar; 
    private AppBarLayout app_bar; 
protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     app_bar = (AppBarLayout) findViewById(R.id.app_bar); 
     toolbar = (Toolbar) findViewById(R.id.toolbar); 
     logToolbarLayoutParams(); 

} 
private void logToolbarLayoutParams() { 
     Log.d(TAG,"Toolbar width/Height"+this.toolbar.getWidth()+"/"+this.toolbar.getHeight()); 
     Log.d(TAG,"App_bar width/height"+this.app_bar.getWidth()+"/"+this.app_bar.getHeight()); 

} 

Я также сослался на этот вопрос в stackoverflow.

final AppBarLayout app_bar = (AppBarLayout) findViewById(R.id.app_bar); 
       ViewTreeObserver vto = app_bar.getViewTreeObserver(); 
       vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
        @Override 
        public void onGlobalLayout() { 
         app_bar.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
         Log.d(TAG, "Global layout"); 
         logToolbarLayoutParams(); 
      } 
     }); 

Если добавить следующий код в мой MainActivity это становится мне правильную высоту и ширину Toolbar. Из вопроса stackoverflow, о котором я упоминал ранее, я узнал, что взгляды не были отображены на экране, поэтому я должен ждать. Но я сомневаюсь, что дизайн, который я указал, не является сложным? почему его занимает много времени, чтобы рисовать на экране? я что-то упускаю?

Я использовал Hierarchy Viewer, чтобы узнать, что заставляет макет ребенка загружаться медленно. Я обнаружил, что я использую mulitple LinearLayout, где single RelativeLayout можно использовать для получения той же структуры. Я изменил свой дизайн макета следующим образом. Все еще я столкнулся с той же проблемой.

обновление: activity_main.xml:

<android.support.design.widget.CoordinatorLayout 
android:layout_width="match_parent" 
android:layout_height="match_parent"> 
<android.support.design.widget.AppBarLayout 
     android:id="@+id/app_bar" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 
     app:layout_behavior="@string/appbar_scrolling_view_behavior"> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="?actionBarSize" 
      android:background="@color/colorPrimary" 
      app:layout_scrollFlags="enterAlways" /> 
    <RelativeLayout 
     android:id="@+id/summary_bottom_sheet" 
     android:layout_width="match_parent" 
     android:layout_height="?actionBarSize" 
     android:layout_gravity="center_horizontal" 
     android:background="@color/colorPrimary"> 


     <TextView 
      android:id="@+id/marked_questions" 
      style="@style/textview_summary_omr_toolbar_count" 
      android:layout_alignParentLeft="true" 
      android:layout_alignParentStart="true" 
      android:background="@drawable/bg_percentage_default" 
      android:text="18" /> 

     <TextView 
      android:id="@+id/marked_textview" 
      style="@style/textview_heading_summary_omr_toolbar" 
      android:layout_toEndOf="@+id/marked_questions" 
      android:layout_toRightOf="@+id/marked_questions" 
      android:text="Marked" /> 


     <TextView 
      android:id="@+id/correct" 
      style="@style/textview_summary_omr_toolbar_count" 
      android:layout_toEndOf="@+id/marked_textview" 
      android:layout_toRightOf="@+id/marked_textview" 
      android:background="@drawable/bg_percentage_6" 
      android:text="18" 

      /> 

     <TextView 
      android:id="@+id/correct_textview" 
      style="@style/textview_heading_summary_omr_toolbar" 
      android:layout_toEndOf="@+id/correct" 
      android:layout_toRightOf="@+id/correct" 
      android:text="Correct" /> 


     <TextView 
      android:id="@+id/wrong" 
      style="@style/textview_summary_omr_toolbar_count" 
      android:layout_toEndOf="@+id/correct_textview" 
      android:layout_toRightOf="@+id/correct_textview" 
      android:background="@drawable/bg_percentage_wrong" 
      android:text="18" /> 

     <TextView 
      android:id="@+id/wrong_textview" 
      style="@style/textview_heading_summary_omr_toolbar" 
      android:layout_toEndOf="@+id/wrong" 
      android:layout_toRightOf="@+id/wrong" 
      android:text="Wrong" /> 


     <TextView 
      android:id="@+id/conflicts" 
      style="@style/textview_summary_omr_toolbar_count" 
      android:layout_toEndOf="@+id/wrong_textview" 
      android:layout_toRightOf="@+id/wrong_textview" 
      android:background="@drawable/bg_percentage_3" 
      android:text="0" /> 

     <TextView 
      android:id="@+id/conflicts_textview" 
      style="@style/textview_heading_summary_omr_toolbar" 
      android:layout_toEndOf="@+id/conflicts" 
      android:layout_toRightOf="@+id/conflicts" 
      android:text="Conflicts" /> 


     <TextView 
      android:id="@+id/score_textview" 
      style="@style/textview_summary_omr_toolbar_count" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_toEndOf="@+id/conflicts_textview" 
      android:layout_toRightOf="@+id/conflicts_textview" 
      android:background="@null" 
      android:gravity="center" 
      android:text="Score:" 
      android:textColor="@android:color/white" /> 

     <TextView 
      android:id="@+id/marks_scored" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_centerVertical="true" 
      android:layout_gravity="center_vertical" 
      android:layout_toEndOf="@+id/score_textview" 
      android:layout_toRightOf="@+id/score_textview" 
      android:gravity="center" 
      android:text="18/30" 
      android:textColor="@android:color/white" 
      android:textSize="18sp" /> 
    </RelativeLayout> 
</android.support.design.widget.AppBarLayout> 
</android.support.design.widget.CoordinatorLayout> 

Следующая иерархия зритель Hierarchy_viewer Image Я получения

+1

Используйте средство просмотра иерархии для проверки макета для проблем с производительностью. https://developer.android.com/studio/profile/optimize-ui.html –

+0

опубликуйте обновленный просмотрер иерархии и ваш Java-код. потому что это может быть не проблема вашей иерархии. – Noorul

+0

Если вы просто спрашиваете, почему вам нужно использовать 'OnGlobalLayoutListener', это потому, что' View 'не будет выложено или нарисовано в' onCreate() '. Вот как это. Это не имеет никакого отношения к вашему конкретному макету или его сложности. –

ответ

3

Вы думаете об этом неправильно. Нет ничего плохого в вашем макете (поскольку это касается вашего вопроса). Чтобы доказать это, полностью изменить свое расположение и повторите попытку

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerView); 
    Log.d("SomeTag", "w: " + recyclerView.getWidth() + ", h: " + recyclerView.getHeight()); 
    Log.d("SomeTag", "mw: " + recyclerView.getMeasuredWidth() + ", mh: " + recyclerView.getMeasuredHeight()); 
} 

Выход для зрения только 1 ребенок до сих пор

12-14 10: 17: 04,902 3004-3004 /? D/SomeTag: w: 0, h: 0

12-14 10: 17: 04.902 3004-3004 /? D/SomeTag: МВТ: 0, ки: 0

Так что нет ничего плохого в макете (кроме вас есть некорректный вызове метод logToolbarLayoutParams, но вы не имеет доступ к раскладке Params вообще. Вы пытаетесь получить свойства объекта просмотра до того, как произошел сбой макета. Возможно, это ваше замешательство). Так что вам не хватает понимания системы макетов Android, групп просмотра и просмотров. У Ромена Гая в один прекрасный момент на Devoxx был очень крутой разговор о том, как создать пользовательский FlowLayout. Либо сайт опускается, либо видео вытягивается, но here's the code in GitHub Если вы посмотрите на метод onLayout, вы увидите, что ViewGroup проходит все дочерние элементы и вызывает child.layout(). Пока этот метод не будет вызван, методы view.getWidth и view.getHeight вернут 0. И этот метод вызывается ОС, когда он планирует его. Таким образом, в основном вы пытаетесь получить доступ к ширине и высоте сразу же до того, как ОС запланировала макет. Создайте пользовательскую группу просмотра самостоятельно, добавьте некоторые точки останова и сделайте снимок.

+0

, спасибо за объяснение. – HourGlass

-2

вы пытаетесь получить ширину и высоту точки зрения, прежде чем его подключенный к экрану вы можете создать пользовательский вид и wath, который вам нужен в методе onAttach

+0

да ahmed мне это известно. Я хочу понять, почему это занимает много времени. Вот почему я искал немного больше, используя просмотр иерархии в ADB – HourGlass

-1

Я только что решил ту же проблему в том же случае. Все решения с ViewTreeObserver.OnGlobalLayoutListener() выглядят грязными и не работают для меня. Самый простой способ узнать ширину и высоту на текущем экране выглядит следующим образом:

toolbar.post(new Runnable() { 
     @Override 
     public void run() { 
      int headerWidth = toolbar.getWidth(); 
      int headerHeight = toolbar.getHeight(); 
      // do whatever you want ... 
     } 
    }); 

view.post() добавит код в конец в очереди сообщений Просмотр в, когда все размеры будут уже вычислили. imho, это очевидно и более понятно, затем OnGlobalLayoutListener(). Надеюсь, это поможет вам.

В любом случае, это решение просто «откладывается на получение размеров», например, OnGlobalLayoutListener(). Но это нормальное поведение системы, для просмотра просмотров на экране требуется некоторое время. Лучший способ не ожидает вычисляемых измерений - вместо этого вы должны координировать все отношения между представлениями в .xml-файлах.Атрибуты, такие как WRAP_CONTENT и MATCH_PARENT, являются самым простым способом решения таких проблем

-1

Нарисованные виды занимают значительное время, но мы можем уменьшить, удалив вложенный макет и сделав иерархию представлений равными либо с помощью RelativeLayout, либо с помощью компоновки Constrain.

Чтобы найти переутомление. Выберите «Показать области переустановки» в параметрах Debug GPU overdraw для разработчиков из настроек.

Исследование this и this важная статья из developer.android по оптимизации раскладки темы

1

toolbar.getWidth() покажет вам ширину зрения после он был измеряется и выложили.
После раздувания зрения его ширина и высота всегда будут 0, потому что не произошло ни measure(), ни layout().

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    toolbar = (Toolbar) findViewById(R.id.toolbar); 

    // check after inflation -> will be 0 
    logToolbarLayoutParams(); 
} 

onGlobalLayout() сообщает правильные данные, так —, как следует из названия — как, onMeasure()иonLayout() были названы. Размеры вида известны. Это делает не означает, что вид был нарисован. onDraw() является третьим и последним шагом.

Также не имеет значения, насколько сложна ваша макет или какие виды вы используете. Пробы измерений и макетов не происходят сразу после инфляции зрения.


Чтобы получить и работать с правильными размерами вашей точки зрения у вас есть 3 варианта:

  1. Используйте ViewTreeObserver.OnGlobalLayoutListener#onGlobalLayout(), как вы уже предложили
  2. Проверьте размер на более позднее время, когда вы можете быть (например, при взаимодействии с пользователем, в OnClickListener)
  3. Идите сами и создайте свой собственный View. Там вы получаете возможность обрабатывать все onMeasure, onLayout и onDraw самостоятельно!
Смежные вопросы