Reputation: 14635
Im trying to create a sort of HUD overlay for Google Cardboard.
The HUD needs to be duplicated (one for each eye). 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.
So i came up with the following solution for a ViewGroup with is supposed to render everything two times:
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);
}
}
The first problem is that neither dispatchDraw or onDraw is called except from one or two times. It is not called when child views are invalidated.
The second problem is that background on elements which has a with of MATCH_PARENT renders outside the ViewGroups inner bounds:
Is this approach hoping for too much, or am i thinking wrong? Creating a completely custom view to handle complex layouts and images seems like lots of work while copying my layout seems like bad design.
Upvotes: 2
Views: 410
Reputation: 10869
This is my thoughts to your problem.
A ViewGroup
hosts View
s; any xml layout are View
s, so extend a ViewGroup
of your choice, either LinearLayout
,Framelayout
-(i prefer), and in your initialisation process, inflate your Layout twice and add them as View
s later you can research on how to use onLayout()
to position your View
s in your preferred Location.
And what ever you call a View
1, View
2 needs to be onboard, you can bind the two, using any approach you want, interfaces or beans
Note
you create one layout and inflate it twice. which will give you two separate View
objects, hence this won't be code duplication as its more of
Elltz _20yearElltz = new Elltz(20),_21yearElltz = new Elltz(21);
Hope it helps
Upvotes: 0
Reputation: 17851
You say:
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.
Actually you can go ahead and use the <include>
tag. All you need to do is create a layout that contains all the views that you are going to show to a single eye
. Then in your main layout you have to <include>
this layout twice, one for the left eye and the other for the right eye.
You might wonder, if this is the case then how can i use findViewById()
on this main layout, since now there will be two views with the same id. Well, you can fix that by doing it as follows. Let's say you have created the eye.xml
layout. Then your main_layout
should look like below.
<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>
When you do the findViewById()
in your code, you could do that as follows:
RelativeLayout leftEye = (RelativeLayout)findViewById(R.id.leftEye);
ImageView iv = (ImageView)leftEye.findViewById(R.id.something);
You need write a simple method in your activity where you just pass the leftEye
or rightEye
as a parameter and perform all code in this method. This lets you perform UI changes in leftEye
and rightEye
simultaneously.
In the future, you could write a custom View in which you could just inflate the eye.xml
. That would modularize your idea.
Upvotes: 2