Как определить высоту DIP области содержимого вкладки? - PullRequest
0 голосов
/ 09 сентября 2011

tl; dr: Как получить высоту DIP для FrameLayout?

Полный: Я пытаюсь создать макет, который согласуется с общими доступными разрешениями. Я ознакомился с передовым опытом разработчиков в Google, и это немного помогло моему пониманию. Я конвертировал иконки в 9-патч и использую высоту DIP, что значительно улучшило ситуацию.

Однако там, где я застрял, пытается воспроизвести три ряда кнопок, которые будут занимать оставшуюся часть экрана, независимо от разрешения. Мне нужно сделать что-то другое для маленьких экранов и планшетов, но в настоящее время я беспокоюсь только о нормальных экранах на большинстве телефонов.

У меня есть макет с TabWidget в качестве роли @android: id / tabs и FrameLayout для @android: id / tabcontent

Одна из операций с вкладками - это просто 3 ряда кнопок, которые я хочу заполнить полностью FrameLayout, и я подозреваю, что должен рассчитать высоту кнопки на основе высоты FrameLayout.

Мой вопрос: как мне получить высоту DIP для FrameLayout?

Я попробовал GlobalLayoutListener, и он просто возвращает 0. Я попытался извлечь LayoutParams, и он только что возвратил -1 для FILL_PARENT. Мне нужна фактическая высота DIP FrameLayout, чтобы правильно установить высоту доступной области.

Как я могу это сделать, или я смотрю на это неправильно?

Любая помощь приветствуется.

1 Ответ

1 голос
/ 09 сентября 2011

Я нашел способ получить желаемый результат, но не совсем так, как пытался, и мне никогда не удавалось получить высоту tabcontent прямо, но косвенно.

Я нашел два способа сделать это, и я опубликую их ниже.

Сначала я сделал Метод 2 , но потом обнаружил, что предпочел Метод 1 и решил пойти с этим, так как он более расширяемый.

Метод 1

Таким образом, я нашел из Как измерить представление Android на основе размеров его родителя , и это наиболее настраиваемый и читаемый метод. В скорлупе ореха вам нужно расширить FrameLayout и переопределить метод onMeasure.

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="0dip"
    android:layout_margin="0dip">
    <LinearLayout
        android:id="@+id/topLayout"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="0dip"
        android:layout_margin="0dip">
        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="50dp"
            android:padding="0dip"
            android:layout_margin="0dip" />
        <view
            class="com.tmcaz.patch.TabContentFrameLayout"
            android:id="@android:id/tabcontent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:padding="0dip"
            android:layout_margin="0dip" />
    </LinearLayout>
</TabHost>

Основное отличие заключается в использовании пользовательского класса для этого, где вы можете обрабатывать размер самого события, аналогично Метод 2 , но нет необходимости выполнять какие-либо вычисления для получения высоты содержимого.

Я сделал это, чтобы получить доступ к событию и обработать все размеры в контенте. Кому-то, читающему это, вполне может понадобиться переопределить что-то еще и совершенно по-другому справиться с событием onMeasure.

код ниже

public class TabContentFrameLayout extends FrameLayout {
        // add constructors, etc
        @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        // Should turn these in to member variables and reference it throughout.
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);

        this.setMeasuredDimension(parentWidth, parentHeight);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

Метод 2

Я назначил id на LinearLayout, который содержал TabWidget и FrameLayout. Вот мой main.xml

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="0dip"
    android:layout_margin="0dip">
    <LinearLayout
        android:id="@+id/topLayout"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="0dip"
        android:layout_margin="0dip">
        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="50dip"
            android:padding="0dip"
            android:layout_margin="0dip" />
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:padding="0dip"
            android:layout_margin="0dip" />
    </LinearLayout>
</TabHost>

Я назначил высоту DIP для tabs, а затем взял LayoutParams для LinearLayout, и я просто вычел высоту tabs из результата. Я добавил код здесь только для иллюстративных целей и могу сделать это немного эффективнее, это не мой рабочий код:)

Одна вещь, на которую стоит обратить внимание, - это то, что вы не можете напрямую задавать высоту макета во время события onCreate, где оно наиболее полезно. Вам нужно создать GlobalLayoutListener, чтобы зафиксировать изменения в макете и получить размер.

public class MyTabActivity extends TabActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        LinearLayout ll = (LinearLayout)findViewById(R.id.topLayout);
        ll.getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {

                    public void onGlobalLayout() {
                        DisplayLayoutDimensions();
                    }
                }
        );

         // Code here to add activities to the tabs, etc
}

.

public void DisplayLayoutDimensions()
{
        // Put code to calculate the heights you need instead of printing
        // out the values obviously.
        Resources r = getResources();
        LinearLayout topLayout = (LinearLayout)findViewById(R.id.topLayout);
        LayoutParams tabWidgetParams = getTabHost().getTabWidget().getLayoutParams();

        float scale = r.getDisplayMetrics().density;
        float pxTabContent = topLayout.getHeight() - tabWidgetParams.height;

        /*** The commented out DIP calculations didn't work for me in any AVD so
             manually I calculated them with the scale which worked fine         ***/

        //float dipTopLayout = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, topLayout.getHeight(), r.getDisplayMetrics());
        //float dipTabWidget = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, tabWidgetParams.height, r.getDisplayMetrics());
        //float dipTabContent = dipTopLayout - dipTabWidget;

        Log.d("MyTabActivity", "LinearLayout (topLayout) Height: " + topLayout.getHeight() + "px / " + (topLayout.getHeight() / scale) + "dp");
        Log.d("MyTabActivity", "TabWidget Height: " + tabWidgetParams.height + "px / " + (tabWidgetParams.height / scale) + "dp");
        Log.d("MyTabActivity", "Calculated (tabcontent) Height: " + pxTabContent + "px / " + (pxTabContent / scale) + "dp");
}

Надеюсь, это поможет кому-нибудь в какой-то момент. Если у кого-то есть лучший способ сделать это, пожалуйста, говорите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...