Create Multiple Views in MirroringFragment


#1

Hi:

I have question, onCreateMirroredContent() only can return one view. If I want to create multiple views in MirroringFragment how should I do? Thank you so much.


#2

You started this over in a GitHub issue — I will quote the important part here:

I mean I can through PresentationFragment mirror parts of Layout on the virtual display. But I need virtual display to extend my mirror, for example, I would like to create some TextView, ImageView or TextureView on the top in virtual display, mirror still working such as background.

You could create your own fork of MirroringPresentationFragment, one that has the MirroringFrameLayout alongside the rest of your desired UI (“some TextView, ImageView or TextureView”).

The question that you posted here is different:

I have question, onCreateMirroredContent() only can return one view. If I want to create multiple views in MirroringFragment how should I do?

A MirroringFragment represents the content that you want to show on both the main display and the external display. If you want lots of things to be mirrored, have onCreateMirroredContent() return a container (e.g., ConstraintLayout) with everything to be mirrored.

If you want additional content on the external display, that would be handled by your Presentation code (whether using my library or rolling it yourself), where you combine a Mirror tied to the MirroringFragment with the rest of your desired UI.


#3

Yeah, these are two different questions. Thank you so much for your nice help! I think I got all I need I will try to make both solution happen, thank you again!


#4

Hi, mmurphy:

I think I still need your help, I have already implemented multiple views mirror base on your answer. But I do not truly understand how to add more additional content on the external display. I think my problem is how to import my mirror into Presentation Class. I am new in this area, please give me more detail guidance to make me know how to do it. Thank you so much.


#5

A Mirror is just a View. So:

  • Create a layout resource that contains a Mirror, plus whatever other stuff you want to show on the external display
  • Use that layout resource with your own subclass of PresentationFragment, inflating that resource in onCreateView()
  • Define some UI on your primary display that you want to mirror
  • Wrap that UI in a MirroringFrameLayout
  • Connect the MirroringFrameLayout and the Mirror

At this point, when you display the PresentationFragment subclass on the external display, it should show a copy of whatever it is that you having the MirroringFrameLayout, plus whatever other widgets you used in the layout resource.


#6

Wow, thank you so much for your fast support. I am trying to make it happen.


#7

Hi mmurphy:

Thank you again for your nice help, I still working on my problem. I think I still not catch the key points.

What I do right now:

I create a layout resource .xml file.

<android.support.constraint.ConstraintLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent">
	<com.commonsware.cwac.layouts.Mirror
		android:layout_width="match_parent"
		android:layout_height="match_parent" />
     <TextureView
	android:id="@+id/test_view"
	android:layout_width="match_parent"
	android:layout_height="match_parent" />

</android.support.constraint.ConstraintLayout>

I create a subclass of PresenationFragment using it inflater layout resource.

public class MyPresentation extends PresentationFragment{
    public static MyPresentation newInstance(Context ctxt, Display display) {
    MyPresentation frag=new MyPresentation();

    frag.setDisplay(ctxt, display);

    return(frag);
}
	@Nullable
	@Override
	public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
		View rootView = inflater.inflate(R.layout.external_display, container, false);
        mirror = rootView.findViewById(R.id.mirroring_source);
    	textureView = rootView.findViewById(R.id.test_view);
		return rootView;
	}
}

I use myPresentation class replace PresenationFragment in my Activity.

but in buildPreso() function IDE show me can not return MirrorPresentationFragment . Looks like I still not catch how to do it. Please give me some help. Thank you so much.


#8

Well…

  • You do not have anything named mirroring_source in that layout
  • You do not have any constraints set on the children of the ConstraintLayout, so it is unlikely to be drawn in a way that you like
  • You do not need a MirrorPresentationFragment in this setup

#9

Hi mmurphy:

Thank you so much for your help.

I have followed your guidance:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:app="http://schemas.android.com/apk/res-auto"
	xmlns:tools="http://schemas.android.com/tools"
	android:layout_width="match_parent"
	android:layout_height="match_parent">

	<android.support.constraint.ConstraintLayout
		android:id="@+id/ui_box"
		android:layout_width="0dp"
		android:layout_height="0dp"
		app:layout_constraintBottom_toBottomOf="parent"
		app:layout_constraintEnd_toEndOf="parent"
		app:layout_constraintStart_toStartOf="parent"
		app:layout_constraintTop_toTopOf="parent">

		<com.commonsware.cwac.layouts.Mirror
			android:id="@+id/mirror_target"
			android:layout_width="0dp"
			android:layout_height="0dp"
			app:layout_constraintBottom_toBottomOf="parent"
			app:layout_constraintEnd_toEndOf="parent"
			app:layout_constraintStart_toStartOf="parent"
			app:layout_constraintTop_toTopOf="parent" />

	</android.support.constraint.ConstraintLayout>

	<TextView
		android:id="@+id/textView"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_marginBottom="139dp"
		android:layout_marginEnd="253dp"
		android:text="Test"
		app:layout_constraintBottom_toBottomOf="parent"
		app:layout_constraintEnd_toEndOf="parent" />
	
</android.support.constraint.ConstraintLayout>

Use that layout resource with your own subclass of PresentationFragment, inflating that resource in onCreateView()

public class MyPresentationFragment extends PresentationFragment{

    	private View rootView;
    	private ConstraintLayout constraintLayout;
    	private Mirror mirror;
    	private TextView textView;

    	public static MyPresentationFragment newInstance(Context context, Display display) {
    		MyPresentationFragment frag = new MyPresentationFragment();
    		frag.setDisplay(context, display);
    		return (frag);
    	}

    	@Nullable
    	@Override
    	public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {

    		rootView = inflater.inflate(R.layout.external_display, container, false);
    		constraintLayout = rootView.findViewById(R.id.ui_box);
    		mirror = rootView.findViewById(R.id.mirror_target);
    		textView = rootView.findViewById(R.id.textView);
    		return (rootView);
    	}
    }

Define some UI on main display layout, and wrap that UI in a MirroringFrameLayout

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:app="http://schemas.android.com/apk/res-auto"
	xmlns:tools="http://schemas.android.com/tools"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	tools:context=".MainActivity">

	<com.commonsware.cwac.layouts.MirroringFrameLayout
		android:id="@+id/mirroring_source"
		android:layout_width="match_parent"
		android:layout_height="match_parent">
		<com.rokid.mirrortest.drawboard.PaletteView
			android:id="@+id/palette"
			android:layout_width="match_parent"
			android:layout_height="match_parent"
			app:layout_constraintBottom_toBottomOf="parent"
			app:layout_constraintEnd_toEndOf="parent"
			app:layout_constraintStart_toStartOf="parent"
			app:layout_constraintTop_toTopOf="parent" />

		<Button
			android:id="@+id/clear"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:layout_marginStart="16dp"
			android:layout_marginTop="16dp"
			android:text="@string/button_clear"
			app:layout_constraintStart_toStartOf="parent"
			app:layout_constraintTop_toTopOf="parent" />
	</com.commonsware.cwac.layouts.MirroringFrameLayout>

</android.support.constraint.ConstraintLayout>

I do not know how to make connections between MirroringFrameLayout and Mirror.

public class MainActivity extends AppCompatActivity implements PresentationHelper.Listener, View.OnClickListener{

	private PresentationHelper presentationHelper;
	private MyPresentationFragment myPresentationFragment;

	private Button buttonClear;
	private PaletteView paletteView;
	private MirroringFrameLayout mirroringFrameLayout;
	private Mirror mirror;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		presentationHelper = new PresentationHelper(this, this);
		mirroringFrameLayout = (MirroringFrameLayout) findViewById(R.id.mirroring_source);
           
		paletteView = findViewById(R.id.palette);
		buttonClear = findViewById(R.id.clear);
        mirroringFrameLayout = (MirroringFrameLayout) findViewById(R.id.mirroring_source);
	    mirror = (Mirror) findViewById(R.id.mirror_target);
	    mirroringFrameLayout.setMirror(mirror);
		buttonClear.setOnClickListener(this);
	}

	@Override
	protected void onStart() {
		super.onStart();
	}

	@Override
	protected void onResume() {
		super.onResume();
		presentationHelper.onResume();
	}

	@Override
	protected void onPause() {
		super.onPause();
		presentationHelper.onPause();
	}

	@Override
	public void showPreso(Display display) {
		myPresentationFragment = buildPreso(display);
		myPresentationFragment.show(getFragmentManager(), "preso");

	}

	private MyPresentationFragment buildPreso(Display display) {
		return(MyPresentationFragment.newInstance(this, display));
	}
	@Override
	public void clearPreso(boolean switchToInline) {
		if(myPresentationFragment != null) {
			myPresentationFragment.dismiss();
			myPresentationFragment = null;
		}
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
            case R.id.clear:
            paletteView.clear();
            break;
        }
	}
}

The code can well run now, which create the external display and show additional UI on the external display, but I do not know how to make connect between MirroringFrameLayout and Mirror, I think I am very close to my goal. Pleae give me more training. Thank you again.


#10

What you want is covered by the CWAC-Layouts documentation. You need to:

  1. Call findViewById() to retrieve your MirroringFrameLayout
  2. Call findViewById() to retrieve your Mirror
  3. Call setMirror() on the MirroringFrameLayout, passing in the Mirror

#11

Yeah, this is what problem I got right now. In MainActivity.class I have did

mirroringFrameLayout = findViewById(R.id.mirroring_source);
mirror = findViewById(R.id.mirror_target); // mirror_target on external_display layout
mirroringFrameLayout.setMirror(mirror);

I try to do something on main display which not mirror on external display.
I think something I did wrong…

I think I know what problem I got. I did one test if I create Mirror view on activity_main.xml which is work. But I need to create Mirror view on external_display.xml, I using MyPresentationFragment.class inflates external_display layout. I need to know how should I can do to passing mirror source to Mirror view on external_display layout.


#12
  1. In your activity, add a setMirror(Mirror) method that calls setMirror() on the MirroringFrameLayout

  2. In onCreateView() of MyPresentationFragment, call ((MainActivity)getActivity()).setMirror(mirror) to supply the Mirror


#13

Thank you so much mmurphy, I already did what I want. Cool! Got much experience from you. Thank you very much! :slight_smile: