两次渲染 ViewGroup 的内容

Render content of ViewGroup twice

我正在尝试为 Google Cardboard 创建一种 HUD 叠加层。

HUD 需要复制(每只眼睛一个)。一个简单的解决方案是手动将所有 XML 元素复制到另一个视图中,但给它们不同的名称。这感觉像是一种糟糕的方法,因为它涉及大量代码重复。

所以我为 ViewGroup 提出了以下解决方案,应该将所有内容渲染两次:

public class StereoView extends FrameLayout {


    private static final String TAG = StereoView.class.getSimpleName();

    public StereoView(Context context) {
        super(context);
        init(context);
    }

    private void init(Context context) {
        testPaint.setColor(Color.RED);
    }

    private Paint testPaint = new Paint(Paint.ANTI_ALIAS_FLAG);


    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right/2, bottom);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {

        canvas.save();
        canvas.translate(getWidth() / 2, 0);

        super.dispatchDraw(canvas);

        canvas.restore();
        super.dispatchDraw(canvas);

    }

    public StereoView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public StereoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }


    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public StereoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }
}

第一个问题是dispatchDraw和onDraw都没有被调用,只有一两次。当子视图失效时不调用它。

第二个问题是具有 MATCH_PARENT 的元素的背景呈现在 ViewGroups 内部边界之外:

200DP 宽度

MATCH_PARENT

这种做法是抱太大希望了,还是我想错了?创建一个完全自定义的视图来处理复杂的布局和图像似乎需要大量工作,而复制我的布局似乎是糟糕的设计。

你说:

A simplistic solution would be to manually copy all the XML elements into another view but giving them different names. This feels like a bad approach since it involves lots of code duplication.

实际上您可以继续使用 <include> 标签。您需要做的就是创建一个布局,其中包含您要访问的所有视图 show to a single eye。然后在你的主布局中你必须<include>这个布局两次,一次用于左眼,另一次用于右眼。

您可能想知道,如果是这种情况,那么我如何在此主布局上使用 findViewById(),因为现在将有两个具有相同 ID 的视图。好吧,您可以按如下方式解决该问题。假设您已经创建了 eye.xml 布局。那么您的 main_layout 应该如下所示。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="horizontal">

     <include
         android:id="@+id/leftEye"
         layout="@layout/eye" />

     <include
         android:id="@+id/rightEye"
         layout="@layout/eye" />

</LinearLayout>

当您在代码中执行 findViewById() 时,您可以按如下方式执行:

 RelativeLayout leftEye = (RelativeLayout)findViewById(R.id.leftEye);
 ImageView iv = (ImageView)leftEye.findViewById(R.id.something);

您需要在 activity 中编写一个简单的方法,您只需将 leftEyerightEye 作为参数传递并执行此方法中的所有代码。这使您可以同时对 leftEyerightEye 执行 UI 更改。

将来,您可以编写一个自定义视图,您可以在其中膨胀 eye.xml。这将使您的想法模块化。

这是我对你的问题的看法。

一个 ViewGroup 主机 View;任何 xml 布局都是 Views,所以扩展你选择的 ViewGroupLinearLayoutFramelayout-(我更喜欢),并在你的初始化过程中, 将你的布局 膨胀两次 并将它们添加为 Views 稍后你可以研究如何使用 onLayout() 将你的 Views 放置在你喜欢的位置地点。

无论你怎么称呼 View 1,View 2 都需要在船上,你可以使用你想要的任何方法、接口或 beans 来绑定这两者

备注

您创建一个布局并将其膨胀两次。这会给你两个单独的 View 对象,因此这不会是代码重复,因为它更多的是

Elltz _20yearElltz = new Elltz(20),_21yearElltz = new Elltz(21);

希望对您有所帮助