3

電卓アプリを持っていて、次のようなレイアウトを作成したい場合すべての画面サイズに合わせてボタンと表示を拡大縮小するにはどうすればよいでしょうか?

私が調べたアイデア:

  1. 各コンポーネントの高さと幅をプログラムで計算します。プログラムでビューを作成すると、最大限の能力が得られますが、理想的ではありません。UI を XML で記述したいと考えています。

  2. レイアウト ウェイトを使用して LinearLayout をネストします。これは機能しますが、ウェイトをネストしているため、lint によってパフォーマンスの警告が表示されます。その上、テキストサイズは考慮されていません。そのため、小さな画面ではテキストが途切れます。逆に、大画面では文字が小さすぎます。

編集: 3. ネストされた重みを持つ TableLayout を使用します。これらが LinearLayout から拡張されていることを考えると、lint 警告の欠如は無関係であると思いますが、これは依然としてパフォーマンスの低下を引き起こしますか?

より良い方法はありますか?明らかな何かが欠けているように感じます

編集 2: 誰かがこのソリューションに興味がある場合は、(raphw が提案したように) カスタム レイアウトを作成し、ソース コードをここに投稿します。

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:

<?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>

そして最終結果:

肖像画 風景

4

2 に答える 2

2

ViewGroup必要な処理を実行するサブクラスを自分で作成するだけで、定義済みのレイアウトを使用する場合と同様に、このレイアウトをXMLレイアウト定義で使用できます。または、GridLayoutクラスを見てください。たぶん、このViewGroup実装はあなたが探していることをすでに行っています。( http://developer.android.com/reference/android/widget/GridLayout.html ) 最終的に、これらのViewGroupレイアウトは含まれるコンポーネントのサイズをプログラムで計算し、View必要な機能を提供する事前定義されたレイアウトがない場合は、他に何もありません。個々の要件を実装するよりも方法。

ただし、ボタンViewインスタンスの責任は、最後のonMeasure.

あなたの例の写真ではレイアウトをネストする必要があり、LinearLayoutクラスは実際に避けるべきです。これはTableLayout.

于 2013-05-11T13:26:48.757 に答える