【问题标题】:Custom ViewGroup incorrect onLayout自定义 ViewGroup 不正确 onLayout
【发布时间】:2015-11-12 10:27:10
【问题描述】:

我正在尝试编写自己的布局类。但我在使用 onLayout 时遇到了问题。如果我扩展 LinearLayout 并让它执行 onLayout 并在我的 onMeasure 中调用 super.onMeasure(),一切正常。但它无法扩展 ViewGroup。显示的是最左边的第一个孩子被正确渲染,但其余的没有显示或尺寸不正确。

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

class ManualPanel extends ViewGroup
{
    private int totalDivs;
    private int[] sizesArr;

    public ManualPanel(final Context context)
    {
        this(context, null);
    }

    public ManualPanel(final Context context, final AttributeSet attrs)
    {
        super(context, attrs);

        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ManualPanel);

        final String[] sizeStr = a.getString(R.styleable.ManualPanel_sizes).split("/");
        final String[] fracArr = sizeStr[0].split(",");
        a.recycle();

        int sum = 0;
        sizesArr = new int[fracArr.length];
        for (int i = 0; i < sizesArr.length; i++) {
            sizesArr[i] = Integer.valueOf(fracArr[i]);
            sum += sizesArr[i];
        }
        totalDivs = Math.max(sum, Integer.valueOf(sizeStr[1]));
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
    {
        final int children = getChildCount();
        final int totalWidth = MeasureSpec.getSize(widthMeasureSpec);
        final int totalHeight = MeasureSpec.getSize(heightMeasureSpec);

        totalDivs = Math.max(totalDivs, children);

        final int[] arr = IntArray.copyOf(sizesArr, children);
        final int width[] = new int[children];
        int sum = 0;

        for (int i = 0; i < children; i++) {
            width[i] = (arr[i] * totalWidth) / totalDivs;
            sum += width[i];
        }
        for (int i = 0, diff = totalWidth - sum; diff > 0; i = ++i % children) {
            width[i]++;
            diff--;
        }
        for (int i = 0; i < children; i++) {
            final View view = getChildAt(i);
            final LayoutParams lp = view.getLayoutParams();

            lp.width = width[i];
            view.setLayoutParams(lp);
            view.measure(MeasureSpec.EXACTLY | lp.width, MeasureSpec.EXACTLY | totalHeight);
        //  view.measure(MeasureSpec.AT_MOST | lp.width, MeasureSpec.AT_MOST | totalHeight);
        }
        setMeasuredDimension(totalWidth, totalHeight);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {
        final int children = getChildCount(), height = getMeasuredHeight();
        for (int i = 0; i < children; i++) {
            final View view = getChildAt(i);

            if (view.getVisibility() != View.VISIBLE)
                continue;

            final int width = view.getMeasuredWidth();
            view.layout(l, 0, left + width, height);
            l += width;
        }
    }
}

【问题讨论】:

  • 快速概览可帮助您正确理解覆盖 ViewGroup。在 onMeasure() 中,您测量 ViewGroup 及其子项的尺寸。在 onLayout() 中,您定位所有孩子并使用测量尺寸进行绘制。在 dispatchDraw() 中,如果你想做任何效果等,你可以覆盖孩子的绘制方式。我也同意 Roman

标签: android android-layout android-custom-view viewgroup


【解决方案1】:

ViewGroup 不知道如何放置孩子。或者如何绘制它们。你必须自己做。

【讨论】:

  • 好吧,我应该将它们放在 onLayout 中。事情正在出现,所以它正在绘制一些东西,只是不是 100% 正确。我需要添加什么?
  • 好吧,绘制调用不应该放在 onLayout onMeasure 方法上
  • 您应该编写自己的 onDraw()。至于怎么做,导入Android源代码并从那里,从现有的Layouts中获取on...程序的文本,并逐步更改这些程序,一个接一个。因此,您可以本地化您的错误。
  • 而且一开始不是基于 LinearLayout 分析 - 它太复杂了,而是基于 FrameLayout。
  • onDraw() 方法不能绘制子视图。 ViewGroup 在其 dispatchDraw() 中调用子绘图方法。 LinearLayout 在其 onDraw() 方法中所做的是在必要时绘制分隔线,它与那里的孩子无关,除了获取有关其大小的信息。
【解决方案2】:

我还没有实际尝试过您的布局。但这是我所看到的。 看你的线

view.layout(l, 0, left + width, height);

您的 left 变量似乎总是为零,因为您没有在循环内更改它。

【讨论】:

  • 好的,我想就是这样,只是我没有正确设置高度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
  • 2011-05-25
  • 2011-08-05
  • 1970-01-01
相关资源
最近更新 更多