I'd like to know how I can put a silhouette on top of a camera preview. So far i've got the following example working, which just previews the Camera.
http://developer.android.com/reference/android/view/TextureView.html
I'm trying to have a Camera preview, where I got a silhouette shown so the person using the app gets an idea of where the picture should be taken, and then a button that when clicked, takes the picture, without the silhouette of course in the picture.
How can this be done? I can't seem to find any examples of how to put an overlay on top of a texture view.
Using the example in the TextureView docs you've linked, we simply create a layout XML file to hold our TextureView and overlay ImageView in a FrameLayout. We then call the Activity's setContentView() method with this layout's Resource ID, instead of the dynamically-created TextureView in the example.
The layout file, main.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextureView android:id="#+id/texture_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView android:id="#+id/image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00000000"
android:src="#drawable/ic_launcher" />
</FrameLayout>
And the sample Activity:
public class LiveCameraActivity extends Activity
implements TextureView.SurfaceTextureListener {
private Camera mCamera;
private TextureView mTextureView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextureView = (TextureView) findViewById(R.id.texture_view);
mTextureView.setSurfaceTextureListener(this);
}
// The TextureView.SurfaceTextureListener methods
// are the same as shown in the example.
...
}
The overlay ImageView in the layout uses the default launcher icon as its source image, as it has transparency, at least on my IDE. You would later replace this image with your silhouette. The ImageView, being listed after the TextureView, will appear on top of it, because Views are drawn with respect to their z-order in the same order they're listed in the layout, with the first View listed being on the bottom; i.e., the farthest away from you on the z-axis.
In the Activity, we're just loading the layout as the content View, and getting a reference to the TextureView created there. Everything else is the same.
Related
I have created a custom SurfaceView which I use to draw shapes, and the user can zoom and pan the view to interact with the shapes. This all works great, but the problem now is that the shapes will always be drawn on top of everything on my screen, also on top of other views such as buttons and textviews. I have tried ordering the custom view and my buttons in different ways in the XML layout, tried parenting the views to FrameLayouts and RelativeLayouts (as suggested here).
I would like to have buttons and other layout elements floating on top of my custom view. As seen in the image below, when I pan my view the rectangle will obscure the buttons.
How can I prevent my custom SurfaceView from drawing on top of everything?
My drawing code runs in a separate thread in the SurfaceView class:
public class CustomShapeView extends SurfaceView implements Runnable, SurfaceHolder.Callback {
/* Other implementation stuff */
#Override
public void run() {
while (isDrawing) {
if (!holder.getSurface().isValid())
continue; //wait till it becomes valid
Canvas canvas = null;
try {
canvas = holder.lockCanvas(null);
synchronized (holder) {
try {
lock.lock();
canvas.concat(sampleMatrix);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
drawShapes(canvas);
} finally {
lock.unlock();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
}
}
My test XML layout, which I would expect to create a button (Left) which is behind the custom view and a button (Right) which is floating above the custom view, is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Left"
android:id="#+id/button"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.CustomShapeView
android:id="#+id/floor_plan_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Right"
android:id="#+id/button2"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
</RelativeLayout>
In my code I was calling the function setZOrderOnTop(true); which made sure that the surface view would always be drawn on top of everything. This piece of code was left in by the previous developer in order to have a custom background for the canvas instead of only a solid color. With SurfaceView it is a tradeoff between having a custom background for the canvas or being able to draw views on top of the canvas.
The options are
With setZOrderOnTop(true); there can be custom backgrounds but no overlaying views.
With setZOrderOnTop(false); there can be overlaying views but only solid color backgrounds for the canvas (by calling e.g. canvas.drawColor(Color.WHITE); to clear between draw calls).
I chose the second option as I value overlaying views over custom backgrounds.
I'm facing a similar issue. I want to put transparent SurfaceView between another views which are being animated in RelativeLayout. When I do so, during animation views sometimes dissapear, sometimes only part of them is visible, it is weird. Then I discovered if I put SurfaceView to the layout first (so at the bottom) and then I call SurfaceView.setZOrderMediaOverlay(true), the content of SurfaceView is drawn at the bottom of the window, view are drawn on the top. If I put SurfaceView anywhere in the layout and then call SurfaceView.setZOrderOnTop(true), the content is always drawn on the top of the window (and also on the top of the views). If I put SurfaceView between views, its behavior is crazy, maybe it's because content of SurfaceView is drawn from separated thread and views are drawn from GUI (main) thread so they are "fighting" and that's why this behavior. Only way I found is drawing at the bottom or at the top. Try to create a new Fragment with transparent background where the SurfaceView is at the bottom as I described in first case and put that buttons you want to have above on top of it (so add them later in some RelativeLayout or FrameLayout) then show this fragment on the top of activity which holds content you want to have below it. Hopefully I helped a bit.
I have a collapsing toolbar with ImageView inside, when the image is clicked I want to enlarge it with an animation and go to another "activity" like whatsapp, telegram and a lot of other apps which allow user to click the profile photo of friends.
This will allow the user to see the image in the center of the screen and save or share the picture.
I had a look of Zooming a View http://developer.android.com/training/animation/zoom.html but it isn't enough and I have lag during the animation. (I used the same code provided)
I think your key is shared element transition. You can follow this tutorial
Give the same transition name to both of the views which are in different activities.
android:transitionName="#string/transition_string"
Add this bundle where you start the zoomed activity
Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(context, view, view.getTransitionName()).toBundle();
startActivity(intent,bundle);
And don't forget to add this line to your activity's style
<!-- Add this line -->
<item name="android:windowContentTransitions">true</item>
You may want to look at Google's documentation on zooming a view here
Basically the way they tell you to go about this is by creating an imagebutton that will display the smaller image, that when clicked will play an animation, and at the end reveal an imageview with the full sized image in it.
The layout they give as an example is this:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<ImageButton
android:id="#+id/thumb_button_1"
android:layout_width="100dp"
android:layout_height="75dp"
android:layout_marginRight="1dp"
android:src="#drawable/thumb1"
android:scaleType="centerCrop"
android:contentDescription="#string/description_image_1" />
</LinearLayout>
<!-- This initially-hidden ImageView will hold the expanded/zoomed version of
the images above. Without transformations applied, it takes up the entire
screen. To achieve the "zoom" animation, this view's bounds are animated
from the bounds of the thumbnail button above, to its final laid-out
bounds.
-->
<ImageView
android:id="#+id/expanded_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
android:contentDescription="#string/description_zoom_touch_close" /></FrameLayout>
Then you can set up the animation like this:
public class ZoomActivity extends FragmentActivity {
// Hold a reference to the current animator,
// so that it can be canceled mid-way.
private Animator mCurrentAnimator;
// The system "short" animation time duration, in milliseconds. This
// duration is ideal for subtle animations or animations that occur
// very frequently.
private int mShortAnimationDuration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zoom);
// Hook up clicks on the thumbnail views.
final View thumb1View = findViewById(R.id.thumb_button_1);
thumb1View.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
zoomImageFromThumb(thumb1View, R.drawable.image1);
}
});
// Retrieve and cache the system's default "short" animation time.
mShortAnimationDuration = getResources().getInteger(
android.R.integer.config_shortAnimTime);
}}
There are several more steps, but at this point I'm literally copy and pasting from their documentation. You really should go read up on it. If you have any questions let me know!
I’m developing an Android drawing app, using a SurfaceView (to be more specific it’s a class that extends SurfaceView). I already saw a lot of topics on this forum, but I didn’t get my answer.
My activity is basically a FrameLayout, which contains all of my views. I would like to set my SurfaceView on the lowest level of my FrameLayout, in order to see the upper elements (buttons, fragments, etc.). I also would like to set the background of my SurfaceView with a drawable but I’m facing problems.
I tried first to set the background of my SurfaceView itself and it works. Unfortunately, my painting content (canvas and bitmap) was overload by this background so I tried a second solution. I apply the drawable background to my FrameLayout, and I set my SurfaceView background as transparent, using setZOrderOnTop. My SurfaceView was indeed transparent, but my drawing stuff was above my buttons and fragments.
So my first question is: why do we need to setZOrderOnTop to get a transparent background? Then, how can I set a simple drawable background, keeping my structure hierarchy?
Thank’s for your answers!
XML View:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/mainFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/repeat_background"
tools:context=".MyActivity">
<!-- Option menu -->
<fragment ... />
<Button ... />
<Button ... />
<Button ... />
...
</FrameLayout>
#drawable/repeat_background
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/drawing_font_texture"
android:tileMode="repeat" />
MyActivity
#Override
protected void onCreate(Bundle p_savedInstanceState) {
super.onCreate(p_savedInstanceState);
setContentView(R.layout.main_controller_activity);
// Getting my FrameLayout
FrameLayout mainFrame = (FrameLayout) findViewById(R.id.mainFrame);
// Instantiating my SurfaceView
this.drawableView = new MCustomDrawableView(getApplicationContext());
// Don't works
//setZOrderMediaOverlay(true);
this.drawableView.setZOrderOnTop(true);
this.drawableView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
FrameLayout.LayoutParams style = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT);
// Add the SurfaceView to the FrameLayout, on lowest position
mainFrame.addView(this.drawableView, 0, style);
}
I think your solution is on the right way. Set the background to the framelayout or add another layout under the surfaceview for your drawable. Then increase the z indices of the surfaceview AND the z indices of the buttons/elements that should be over the surfaceview,otherwise they are under it.
If you use material design, you can also set the elevation in dp for nice shadows.
I'm very new to Java, and I'm trying to create an app where you can use the gyroscope to move an image on the screen, so that it looks like the image is sticked to an object in from the camera. The image is finished, and I got it moving, just like it should. Now I only need the camera as background of the xml file. Is there any simple ways to do this?
Use a FrameLayout as parent layout of activity. Then place a Surfaceview to show a custom camera. Then you can place any layout on top of it to show other components. This is will look like a camera in background. For more info on placing camera on SufaceView, please check this
Essentially, you want to make the camera preview the first element in the first Layout object in the XML file.
You can use any of the Layout types based on how you would like to layout the other controls. I used a RelativeLayout as the base for my layout here. The FrameLayout with an id of 'camera_preview' is used as a container for the camera preview class.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
tools:context=".YourMainActivity" >
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<!-- ... other display controls ... -->
</RelativeLayout>
Then, in YourMainActivity's onCreate() create a new instance of your camera preview class and add it to the camera_preview container in your layout:
private static YourCameraPreviewClass mPreview;
#Override
protected void onCreate(Bundle savedInstanceState) {
// ... get camera instance ...
mPreview = new YourCameraPreviewClass( this, cameraInstance );
FrameLayout previewFrameLayout = (FrameLayout) findViewById( R.id.camera_preview );
previewFrameLayout.addView( mPreview );
Log.d( LOGTAG, "Camera preview background set! (:" );
}
I want to display an image preview over my app: when user presses an item in the listview (each item is a path to an image stored in sd card) image preview appears,stretched in the available space, like in this picture (image space is black, underlying app, still partially visible, is gray):
when user presses back image disappear.
I thought to make an activity just for image displaying but I don't know how to obtain the result in the picture...
Edit:
Ok here's what I've done so far:
1)Manifest:
<activity
android:name=".ImageDialogActivity" android:theme="#android:style/Theme.Dialog">
</activity>
2)Layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
3)Activity onCreate method:
super.onCreate(savedInstanceState);
setContentView(R.layout.image_preview);
String filepath = getIntent().getStringExtra("image_filepath");
((ImageView)findViewById(R.id.imageView)).setImageBitmap(getBitmap(filepath));
where getBitmap is a private method which gives me a bitmap from a filepath.
Problem is that I don't have control over dialog dimensions: dialog's width and height seem to depend on contained image ones...not to mention top/right/left/bottom margins...
Solved (maybe):
I modified layout file this way:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="200dp"
>
<ImageView android:id="#+id/imageView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerInside"/>
Setting width/height to a square allowed to obtain the effect...my question is: will it work for every phone?Or it is right just for mine?
Your best shot is to display your image in a Dialog
If you then want more control over the display, theme it
If you want to do this by creating a new Activity, you should set its layout parameters to wrap_content so it will appears above the other activity but not fitting the screen totally. Also by setting its theme as Theme.Dialog or an inherited theme, you 2nd activity will be a little bit darker and your activity will appear like a dialog.
You should also try to put layout parameter to fill_parent and add margins if you want the exact result as you shown (don't know if this solution could work).
this is from api demos creating an activit like a dilog try this
public class DialogActivity extends Activity {
/**
* Initialization of the Activity after it is first created. Must at least
* call {#link android.app.Activity#setContentView setContentView()} to
* describe what is to be displayed in the screen.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
// Be sure to call the super class.
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_LEFT_ICON);
// See assets/res/any/layout/dialog_activity.xml for this
// view layout definition, which is being set here as
// the content of our screen.
setContentView(R.layout.dialog_activity);
getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
android.R.drawable.ic_dialog_alert);
}
}
Solved, solution entered in main post seems working fine!