2

我正在尝试为 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 在此处输入图像描述

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

4

2 回答 2

2

你说:

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

实际上你可以继续使用<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);

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

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

于 2015-10-25T11:30:29.473 回答
0

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

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

无论你称之为View1、2的东西都View需要在船上,你可以使用任何你想要的方法、接口或 bean 来绑定两者

笔记

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

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

希望能帮助到你

于 2015-10-27T00:40:37.767 回答