I've a surfaceview to do some drawing stuff. My view supports zoom in/out feature. Now when user zoom in/out by finger gesture, I want to resize the surfaceview, I've tried resizing by changing surfaceview's layout params. Although this works, but it's slow, and while doing the resize work, I see some big jumps (lags), Which is no usable. Here, I want to know how can I resize the surfaceview efficiently (without that jump)?
Here sniped of my view structure,
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:fillViewport="true"
android:layout_above="#+id/bottomMenu"
android:layout_height="match_parent">
<MySurfaceView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout> ...
And the params changing code,
ViewGroup.LayoutParams params = surface.getLayoutParams();
params.height = (int) (750*factor);
surface.setLayoutParams(params);
Well in the end I found a method of surfaceHolder to set the canvas size fixed,
holder.setFixedSize(canvasW, canvasH);
With this method I'm able to resize layout with layout params, without any kind of lagging. Here, I need to know the canvas size before setting it up, so I added my SurfaceView from Java code with predefined size and it's working smoothly.
**I'm not still sure, why setting up canvas fixed size done the trick. You are welcome to explain a bit (may be edit this answer).
Related
I am trying to use PhotoView and I would like the image to be shown like it is in Android's Wallpaper app.
So it seems that the images in the wallpaper app are scaled down or up to fill the of the screen, but the width is seemingly unchanged such that if you want to view the whole picture you either have to zoom or scroll left and/or right? Is this making use of the setDisplayMatrix method? If so how would that method call look? Here is a sample of my xml, but I am making use of Glide to set the image, if I need to drop Glide and just use the PhotoView widget directly I am will to do that too if that would produce the desired effect.
<com.github.chrisbanes.photoview.PhotoView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/photoView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:showIn="#layout/activity_wallpaper_viewer"/>
Threw the image into a HorizontalScrollView, changed the xml a bit to this
<com.github.chrisbanes.photoview.PhotoView
android:id="#+id/photoView" android:adjustViewBounds="true"
android:layout_width="wrap_content" android:layout_height="match_parent"/>
Simple... Embarrassing...
Now I know how to make the translateAnimation, in order to go through the picture, and show it on the screen.
What I do not know how to do, is put the picture on the screen, and make it in such a way so that it will not scale it by the scale type. So I can start the translateAnimation.
I saw some posts about this, and a lot of suggestions are saying I should use a HorrizontalScrollView, in order to put a picture bigger than the device screen. But I need to make a animation go thought it, and not for me to be able to move the picture, so in my opinion that might not be the perfect way to go.
Do you guys have any other suggestions?
Did not use a horrizontalScrollView, instead, forced the width of the whole layout to be the size of a picture, set a RelativeLayout inside, with the size of the screen, and then made the animations.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="1103dp"
android:layout_height="736dp"
android:background="#color/white">
<ImageView
android:id="#+id/background"
android:visibility="invisible"
android:src="#drawable/story1"
android:scaleType="fitXY"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<RelativeLayout
android:id="#+id/screen_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
-----------------CODE inside relative layout for normal page--------
</RelativeLayout>
</RelativeLayout>
Then inside my code I set the screen width and height for my screen container (containing everything except the background picture which will translate):
screenContainer.setLayoutParams(new RelativeLayout.LayoutParams(Math.round(Constants.screenWidth), Math.round(Constants.screenHeight)));
This is my Translation for the ImageView that matches the parent (the size of the background pic):
TranslateAnimation translateBackground = new TranslateAnimation(
TranslateAnimation.RELATIVE_TO_PARENT,from,
TranslateAnimation.RELATIVE_TO_PARENT,-0.5f,
TranslateAnimation.RELATIVE_TO_PARENT,0.0f,
TranslateAnimation.RELATIVE_TO_PARENT,0.0f);
translateBackground.setDuration(15000);
background.setVisibility(View.VISIBLE);
background.startAnimation(translateBackground);
I have an image like this used as background in a RelativeLayout:
This image is used as background for all the levels of my game. Every level is drawn onto the blue area.
I want to keep fixed the aspect-ratio of the blue area, changing the size of the red edges to avoid to show to the user unused pixels of their screen. The green area must be fixed to 80dp for all phones. Then I must add a View (a GLSurfaceView) in my layout in such a way that it fit perfectly the blue area. Thus all levels of my Android game will be perfectly the same in all Android device.
How can I solve this problem?
The real image that I use is a little more complex. You can look it here:
Real image
I would use a FrameLayout for the middle part of the screen(blue), add an ImageView, containing the BackgroundImage you want to display, and put the GLSurfaceView on top of it.
Since the aspect ratio is always the same, you could set the ImageViews sclaing to fit xy and the image should always look the same.
Lets assume you are using a simple SurfaceView, the xml code id use to put a ImageView begind it would look like this
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_height="match_parent"
android:layout_width="match_parent"/>
<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
As i dont know how you build your View i cant post the code that does the job, but just add a FrameLayout instead of your GLSurfaceView to your View, with the Same Dimensions, the GLSurfaceView would have.
To that FrameLayout first add the ImageView, then the GLSurfaceView. Both with height and width set to match_parent.
To Figure out the size of your SurfaceView...
Retrieve Display Dimensions
Substract Green Bar Dimensions
Calculate the size of the Blue View, get the Height/Width (whatever is bigger) calculate the missing Dimension
Set the Red Views to Occupie the empty space.
So you would have to do this programmatically :)
I'm developing an app that shows a camera preview on a SurfaceView but I only want to show the top half of the preview.
Is there a way of cropping/clipping the view or will I have to resort to obscuring the bottom half with something like an image,other view or drawing?
regards
Simon
I am currently using this method to do the cropping (basically using the clip child ability of an absolute layout to clip a surfaceview child)
<AbsoluteLayout android:clipChildren="true" android:layout_alignParentRight="true" android:layout_width="240dp" android:id="#+id/absoluteLayout1" android:layout_height="80dp">
<SurfaceView android:id="#+id/swSurfaceView" android:layout_width="240dp" android:layout_height="160dp" android:visibility="visible"></SurfaceView>
</AbsoluteLayout>
Overlaying the SurfaceView with another view is the easiest way to do it... however, it's quite ugly if you ask me.
Why don't just set the SurfaceView height manually? Make it take the 50% of the screen space and it will do what you want. You don't provide code so we'll have to do some guesses: let's suppose you have a LinearLayout, then inside it you put two views: your surface view and another kind of view. Then, you set their height to be 0dip, and their weight to be 1... that should do it.
I have an application with a SurfaceView and a MapView. They are displayed in a single view, like so:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.google.android.maps.MapView
android:id="#+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="XXXXXXXXredactedXXXXXXXXXXXXx"
/>
<class.that.extends.SurfaceView
android:id="#+id/surfaceview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#00000000"
/>
</RelativeLayout>
Note the MapView comes before the SurfaceView. Because of this, the MapView is drawn "under" the SurfaceView, and all that I see is a black background, with the things that I draw on the SurfaceView showing. If I swap the order, and put SurfaceView first in the file and MapView second, the MapView is drawn, with none of the SurfaceView showing.
According to the SurfaceView Javadoc:
The surface is Z ordered so that it is behind the window holding its SurfaceView; the SurfaceView punches a hole in its window to allow its surface to be displayed. The view hierarchy will take care of correctly compositing with the Surface any siblings of the SurfaceView that would normally appear on top of it.
To me, this means that I should be able to put the SurfaceView first in the file, and have it "punch through" the MapView and display what it has. But, as it is, they seem to be two views, and only one is visible at a time.
After thought: I tried setting the background to #00000000 so that the alpha of the background would be zero (i.e. transparent), but it doesn't have any effect.
The alpha setting alone won't really help in this case.
When you setup your views, set the PixelFormat of the view's SurfaceHolder:
glsView = (GLSurfaceView) findViewById(R.id.surfaceview);
glsView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
I ended up abandoning SurfaceView, despite it's wonderful features for drawing smoothly. Now I'm just using a regular old View, overriding its onDraw method. The MapView underneath is currently being refreshed every time this new View is drawn, but I'm looking in to using the drawing cache feature of Views to simplify that.