Android的 - 如何扩展的意见,以适应全屏幕应用程序的高度和宽度完美? [英] Android - How do you scale views to fit a full screen application's height and width perfectly?

查看:477
本文介绍了Android的 - 如何扩展的意见,以适应全屏幕应用程序的高度和宽度完美?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果你有一个计算器应用程序,你想写一个布局,看起来像这个,你怎么缩放按钮和显示以适合所有屏幕尺寸?

If you have a calculator app and you want to write a layout that looks like this, how do you scale the buttons and display to fit on all screen sizes?

想法,我已经调查:


  1. 编程方式计算每个组件的高度和宽度。编程方式创建视图为您提供了最省电,但并不完全理想。我想preFER写我的XML UI。

  1. Programatically calculating the height and width of each component. Programatically creating the views gives you the most power, but is not exactly ideal. I'd prefer to write my UI in XML.

嵌套LinearLayouts与布局权重。这工作,但lint会给出性能警告,因为我嵌套的权重。最重要的是,它没有考虑到文本大小。因此,小屏幕,文本被剁掉。相反,在大屏幕上,文字是太小了。

Nesting LinearLayouts with Layout weights. This works, but lint gives performance warnings because I am nesting weights. On top of that, it does not take into account text size. So on small screens, text is chopped off. Conversely, on large screens, text is too small.

编辑:
3.使用嵌套权重TableLayout。考虑到这些来自的LinearLayout延伸,我认为缺乏lint警告是无关紧要的,这仍然会导致性能权利的丧失?

3. Using a TableLayout with nested weights. Considering these extend from LinearLayout, I assume the lack of lint warnings is irrelevant, this is still going to cause a loss in performance right?

有没有更好的办法?我觉得我失去了一些东西明显

Is there a better way? I feel like I am missing something obvious

编辑2:
如果有人有兴趣这样做的解决方案,我创建了一个自定义布局(如raphw建议),并会在这里发布源$ C ​​$ C:

EvenSpaceGridLayout.java:

EvenSpaceGridLayout.java:

package com.example.evenspacegridlayout;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

public class EvenSpaceGridLayout extends ViewGroup {

    private int mNumColumns;

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

    public EvenSpaceGridLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.EvenSpaceGridLayout);
        try {
            mNumColumns = a.getInteger(
                    R.styleable.EvenSpaceGridLayout_num_columns, 1);
        } finally {
            a.recycle();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        // Calculate how many cells we need
        int cellCount = countCellsNeeded();

        // Calculate number of rows needed given the number of cells
        int numRows = cellCount / mNumColumns;

        // Calculate width/height of each individual cell
        int cellWidth = widthSize / mNumColumns;
        int cellHeight = heightSize / numRows;

        // Measure children
        measureChildrenViews(cellWidth, cellHeight);

        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            LayoutParams lp = (LayoutParams) child.getLayoutParams();
            child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y + child.getMeasuredHeight());
        }
    }

    private int countCellsNeeded() {

        int cellCount = 0;
        final int childCount = getChildCount();

        for (int i = 0; i < childCount; i++) {

            View child = getChildAt(i);
            LayoutParams lp = (LayoutParams) child.getLayoutParams();

            int spanColumns = lp.spanColumns;

            // If it's trying to span too far, make it span the maximum possible
            if (spanColumns > mNumColumns) {
                spanColumns = mNumColumns;
            }

            int remainingCellsInRow = mNumColumns - (cellCount % mNumColumns);
            if (remainingCellsInRow - spanColumns < 0) {
                cellCount += remainingCellsInRow + spanColumns;
            } else {
                cellCount += spanColumns;
            }
        }

        // Round off the last row
        if ((cellCount % mNumColumns) != 0) {
            cellCount += mNumColumns - (cellCount % mNumColumns);
        }

        return cellCount;
    }

    private void measureChildrenViews(int cellWidth, int cellHeight) {

        int cellCount = 0;
        final int childCount = getChildCount();

        for (int i = 0; i < childCount; i++) {

            View child = getChildAt(i);
            LayoutParams lp = (LayoutParams) child.getLayoutParams();

            int spanColumns = lp.spanColumns;

            // If it's trying to span too far, make it span the maximum possible
            if (spanColumns > mNumColumns) {
                spanColumns = mNumColumns;
            }

            // If it can't fit on the current row, skip those cells
            int remainingCellsInRow = mNumColumns - (cellCount % mNumColumns);
            if (remainingCellsInRow - spanColumns < 0) {
                cellCount += remainingCellsInRow;
            }

            // Calculate x and y coordinates of the view
            int x = (cellCount % mNumColumns) * cellWidth;
            int y = (cellCount / mNumColumns) * cellHeight;

            lp.x = x;
            lp.y = y;

            child.measure(MeasureSpec.makeMeasureSpec(cellWidth * spanColumns, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(cellHeight, MeasureSpec.EXACTLY));

            cellCount += spanColumns;
        }
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p instanceof LayoutParams;
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
        return new LayoutParams(p.width, p.height);
    }

    public static class LayoutParams extends ViewGroup.LayoutParams {

        int x, y;

        public int spanColumns;

        public LayoutParams(Context context, AttributeSet attrs) {
            super(context, attrs);
            TypedArray a = context.obtainStyledAttributes(attrs,
                    R.styleable.EvenSpaceGridLayout_LayoutParams);
            try {
                spanColumns = a
                        .getInteger(
                                R.styleable.EvenSpaceGridLayout_LayoutParams_span_columns,
                                1);

                // Can't span less than one column
                if (spanColumns < 1) {
                    spanColumns = 1;
                }
            } finally {
                a.recycle();
            }
        }

        public LayoutParams(int w, int h) {
            super(w, h);
        }
    }
}

attrs.xml:

attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="EvenSpaceGridLayout">
        <attr name="num_columns" format="integer" />
    </declare-styleable>

    <declare-styleable name="EvenSpaceGridLayout_LayoutParams">
        <attr name="span_columns" format="integer" />
    </declare-styleable>

</resources>

使用方法如下:

<com.example.evenspacegridlayout.EvenSpaceGridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:grid="http://schemas.android.com/apk/res/com.example.evenspacegridlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    grid:num_columns="4" >

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="CL" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Del" />

    <!-- empty cell -->
    <View 
        android:layout_width="0dp"
        android:layout_height="0dp" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="/" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="7" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="8" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="9" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="*" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="4" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="5" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="6" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="-" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="1" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="2" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="3" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="+" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="." />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="0" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="="
        grid:span_columns="2" />

</com.example.evenspacegridlayout.EvenSpaceGridLayout>

和最终的结果:


推荐答案

您可以简单地写的ViewGroup 继承自己该做你想要什么,在仍然使用这种布局的 XML 的就像你使用任何predefined布局布局定义。另外,看网​​格布局类。也许这的ViewGroup 实施已经这样做了,你在找什么。 ( http://developer.android.com/reference/android/widget/GridLayout。 HTML )最后,这些的ViewGroup 布局编程计算它们包含查看组件的大小,如果pdefined布局没有$ p $提供所需的功能,有没有其他方式比实现您的个性化需求。

You could simply write a ViewGroup subclass yourself which does what you want and still use this layout in an XML layout definition just as you would use any predefined layout. Alternatively, look at the GridLayout class. Maybe this ViewGroup implementation already does what you are looking for. (http://developer.android.com/reference/android/widget/GridLayout.html) In the end, these ViewGroup layouts programatically compute the size of their contained View components and if no predefined layout offers the functionality you require, there is no other way than implementing your individual requirements.

然而,它应该保持按钮的责任查看实例,以保持他们的内容范围之内了他们最新的的通话过程中,他们收到的大小onMeasure

However, it should remain the responsibility of the button View instances to keep their content within the scope the size they received during their latest call of onMeasure.

嵌套布局的扩大就必须与你的榜样图片,确实应该避免在的LinearLayout 类。应当指出的是仍然是因为这是一个常见的​​做法是使用时隐式地完成一个 TableLayout

Nesting layouts to the extend it would be necessary with your example picture and the LinearLayout class should indeed be avoided. It should be noted that is nevertheless a common practice since this is done implicitly when using a TableLayout.

这篇关于Android的 - 如何扩展的意见,以适应全屏幕应用程序的高度和宽度完美?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆