I'm trying to draw a rectangle over camera2 textureview, when i run the code I see the usual camera screen with moving square , and when I Click (touch) it, app crashes with the error in topic. I also not sure I implemented the custom view correctly, Here are all the relevant parts, Would love some help (I'm not sure I have a good layout xml, I added ViewGroup code under OnCrearte, not sure i even need to touch xml)
-------CameraActivity.java:
package com.example.android.camera2video;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.ViewGroup;
public class CameraActivity extends Activity {
private Context context;
CustomView customview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
customview = new CustomView(this);
final ViewGroup viewGroup = (ViewGroup) ((ViewGroup) this.findViewById(android.R.id.content)).getChildAt(0);
viewGroup.addView(new CustomView(this));
if (null == savedInstanceState) {
getFragmentManager().beginTransaction()
.replace(R.id.container, Camera2VideoFragment.newInstance())
.commit();
}
}
}
-------CustomView.java
package com.example.android.camera2video;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CustomView extends SurfaceView {
private Paint paint;
private SurfaceHolder mHolder;
private Context context;
public CustomView(Context context) {
super(context);
mHolder = getHolder();
mHolder.setFormat(PixelFormat.TRANSPARENT);
this.context = context;
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
}
public CustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// real work here
}
private void doAdditionalConstructorWork() {
// init variables etc.
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
invalidate();
if (mHolder.getSurface().isValid()) {
final Canvas canvas = mHolder.lockCanvas();
Log.d("touch", "touchRecieved by camera");
System.err.println("EXIT 1");
if (canvas != null) {
Log.d("touch", "touchRecieved CANVAS STILL Not Null");
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawColor(Color.TRANSPARENT);
canvas.drawCircle(event.getX(), event.getY(), 100, paint);
mHolder.unlockCanvasAndPost(canvas);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Canvas canvas1 = mHolder.lockCanvas();
if(canvas1 !=null){
canvas1.drawColor(0, PorterDuff.Mode.CLEAR);
mHolder.unlockCanvasAndPost(canvas1);
}
}
}, 1000);
}
mHolder.unlockCanvasAndPost(canvas);
}
}
return false;
}
}
-----fragment_camera2_video.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.android.camera2video.AutoFitTextureView
android:id="#+id/texture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_below="#id/texture"
android:background="#4285f4">
<Button
android:id="#+id/video"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="#string/record" />
<ImageButton
android:id="#+id/info"
android:contentDescription="#string/description_info"
style="#android:style/Widget.Material.Light.Button.Borderless"
android:layout_width="4dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|right"
android:padding="20dp"
android:src="#drawable/ic_action_info" />
</FrameLayout>
</RelativeLayout>
Only one thing can be drawing to a View at a time; once the SurfaceView is connected to the camera, you're not able to lock it for drawing yourself.
Your crash is probably because you're calling mHolder.unlockCanvasAndPost(canvas); outside of the null check.
If you want to draw over the cameara preview, you need a second View positioned on top of the SurfaceView.
Related
After extending the ScrollView class I was able to easily be notified of the scrolling in realtime.
Now I need to capture the content of this scrollview in a very specific part.
Let's say I want to capture the top of the screen (matching parent width and a defined height, like 100dp). But only the content of the ScrollView and not the rest, if there is anything else on the top but not as part of the ScrollView.
I tried using on the scrollview :
setDrawingCacheEnabled(true);
getDrawingCache(true);
setDrawingCacheEnabled(false);
Then I tried to crop so that I get the part I want :
Bitmap.createBitmap(complete, 0, 0, width, height);
Results are very far from what I want to achieve and performance are very very poor and at some point I would get either a SIGENV or getDrawingCache(true) tries to use a recycled bitmap...
So how can I easily capture the content in the desired area without too much performance hit ?
Note: this process must be done as I am scrolling the content, so inside ScrollView's onScrollChanged(final int x, final int y).
Thanks !
Since the problem was fun I implemented it, it seems to work fine. I guess that you are recreating a Bitmap each time that's why goes slow.
The idea is like this, you create an area in the ScrollView that you want to copy (see Rect cropRect and Bitmap screenshotBitmap), it's full width and you just need to set the height. The view automatically set a scroll listener on itself and on every scroll it will copy that area. Note that setDrawingCacheEanbled(true) is called just once when the view is instantiated, it basically tells the view that you will call getDrawingCache(), which will return the Bitmap on which the view is drawing itself. It then copy the area of interest on screenshotBitmap and that's the Bitmap that you might want to use.
ScreenshottableScrollView.java
package com.example.lelloman.screenshottablescrollview;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.view.ViewTreeObserver;
import android.widget.ScrollView;
/**
* Created by lelloman on 16-2-16.
*/
public class ScreenshottableScrollView extends ScrollView implements ViewTreeObserver.OnScrollChangedListener {
public interface OnNewScreenshotListener {
void onNewScreenshot(Bitmap bitmap);
}
private Bitmap screenshotBitmap = null;
private Canvas screenshotCanvas = null;
private int screenshotHeightPx = 0;
private OnNewScreenshotListener listener = null;
private Rect cropRect;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public ScreenshottableScrollView(Context context) {
super(context);
init();
}
public ScreenshottableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ScreenshottableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ScreenshottableScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init(){
setDrawingCacheEnabled(true);
getViewTreeObserver().addOnScrollChangedListener(this);
}
public void setOnNewScreenshotListener(OnNewScreenshotListener listener){
this.listener = listener;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if(screenshotHeightPx != 0)
makeScrenshotBitmap(w,h);
}
public void setScreenshotHeightPx(int q){
screenshotHeightPx = q;
makeScrenshotBitmap(getWidth(), getHeight());
}
private void makeScrenshotBitmap(int width, int height){
if(screenshotBitmap != null) screenshotBitmap.recycle();
if(width == 0 || height == 0) return;
screenshotBitmap = Bitmap.createBitmap(width, screenshotHeightPx, Bitmap.Config.ARGB_8888);
screenshotCanvas = new Canvas(screenshotBitmap);
cropRect = new Rect(0,0,width,screenshotHeightPx);
}
#Override
public void onScrollChanged() {
if(listener == null) return;
Bitmap bitmap = getDrawingCache();
screenshotCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
screenshotCanvas.drawBitmap(bitmap,cropRect, cropRect,paint);
listener.onNewScreenshot(screenshotBitmap);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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="vertical"
tools:context="com.example.lelloman.screenshottablescrollview.MainActivity">
<com.example.lelloman.screenshottablescrollview.ScreenshottableScrollView
android:id="#+id/scrollView"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.example.lelloman.screenshottablescrollview.ScreenshottableScrollView>
<View
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="#ff000000"/>
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="100dp" />
</LinearLayout>
MainActivity.java
package com.example.lelloman.screenshottablescrollview;
import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StringBuilder builder = new StringBuilder();
Random random = new Random();
String AB = "abcdefghijklmnopqrstuvwxyz ";
for(int i=0;i<100;i++){
builder.append("\n\n"+Integer.toString(i)+"\n\n");
for(int j =0;j<1000;j++){
builder.append(AB.charAt(random.nextInt(AB.length())));
}
}
((TextView) findViewById(R.id.textView)).setText(builder.toString());
final ImageView imageView = (ImageView) findViewById(R.id.imageView);
ScreenshottableScrollView scrollView = (ScreenshottableScrollView) findViewById(R.id.scrollView);
scrollView.setScreenshotHeightPx((int) (getResources().getDisplayMetrics().density * 100));
scrollView.setOnNewScreenshotListener(new ScreenshottableScrollView.OnNewScreenshotListener() {
#Override
public void onNewScreenshot(Bitmap bitmap) {
Log.d("MainActivity","onNewScreenshot");
imageView.setImageBitmap(bitmap);
}
});
}
}
I have 3 views:
GLSurfaceView
Custom SurfaceView
View
The GLSurfaceView is at the bottom
The Custom SurfaceView should be above and on the top
The View is above and on the bottom
This is my code:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
GameGlSurfaceView gameGlSurfaceView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameGlSurfaceView = new GameGlSurfaceView(this);
setContentView(gameGlSurfaceView);
View hudView = getLayoutInflater().inflate(R.layout.activity_main, null);
addContentView(hudView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
View inpudPadView = getLayoutInflater().inflate(R.layout.input_pad, null);
LinearLayout.LayoutParams inpudPadViewParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
inpudPadViewParams.gravity = Gravity.TOP;
addContentView(inpudPadView, inpudPadViewParams);
}
}
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class SurfacePanel extends SurfaceView implements SurfaceHolder.Callback {
Context context;
Bitmap bitmapTest;
MyThread mythread;
public SurfacePanel(Context ctx, AttributeSet attrSet ) {
super(ctx, attrSet);
context = ctx;
bitmapTest = Bitmap.createBitmap(200, 100, Bitmap.Config.ARGB_8888);
bitmapTest.eraseColor(Color.TRANSPARENT);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
}
void doDraw(Canvas canvas) {
canvas.drawColor(Color.GREEN);
canvas.drawBitmap(bitmapTest, 50, 10, null);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mythread = new MyThread(holder, context,this);
mythread.setRunning(true);
mythread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mythread.setRunning(false);
boolean retry = true;
while(retry) {
try {
mythread.join();
retry = false;
}
catch(Exception e) {
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context="de.batechniks.surfaceviewtest.MainActivity">
<de.batechniks.surfaceviewtest.SurfacePanel
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/textView"/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:baselineAligned="false"
xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="left">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/bt_down"
android:src="#mipmap/ic_launcher"
android:layout_gravity="bottom"/>
</LinearLayout>
The result is: I can see the GLSurfaceView and i can see the view above on the bottom.
On the top, i only see the textview "Large Text". The SurfaceView is not shown.
When i uncomment setContentView(gameGlSurfaceView), the SurfaceView is shown.
The main problem is to show the SurfaceView, the second problem will be to get the SurfaceView transparent.
Thanks a lot
You need to call the method
this.setZOrderOnTop(true);
in your constructors.
It's recommended to do constructors in custom views like this
public SurfacePanel (Context context) {
super(context);
init();
}
public SurfacePanel (Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SurfacePanel (Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#TargetApi(21)
public SurfacePanel (Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
if(!isInEditMode()) {
this.setZOrderOnTop(true);
}
}
I am following this tutorial: http://danielnadeau.blogspot.ca/2012/01/android-canvas-beginners-tutorial.html
When I look at things in the "Graphical Layout" tab in Eclipse, I see the expected result (a red square in the center of the display), but when I actually run the app, I just get a large black rectangle, and I can't seem to figure out why. I've searched some posts, but have not found an answer that seems to apply to my situation.
MainActivity.java
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
activity_mail.xml
<RelativeLayout 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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<com.hintonworks.cantstop.CustomView
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="#+id/my_view" />
</RelativeLayout>
CustomView.java
package com.hintonworks.cantstop;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CustomView extends SurfaceView implements SurfaceHolder.Callback {
public CustomView (Context context) {
super(context);
}
public CustomView (Context context, AttributeSet attrs) {
super(context);
}
#Override
public void onDraw (Canvas canvas) {
int dCenter = 40; //Distance from center in px, NOT in dp
int centerX = (int)(getWidth()/2);
int centerY = (int)(getHeight()/2);
Paint paint = new Paint();
paint.setColor(Color.RED); //The square will draw in the color blue now
Rect rect = new Rect(centerX-dCenter, centerY-dCenter, centerX+dCenter, centerY+dCenter);
canvas.drawRect(rect, paint);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
#Override
public void surfaceCreated(SurfaceHolder holder) {
setWillNotDraw(false); //Allows us to use invalidate() to call onDraw()
postInvalidate();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {}
}
Thanks for any insight. This is my stab at using the canvas, until now I have been using drawable resources.
I am trying to develop a simple map application, which will display a map in the screen.
When the user moves the cursor on screen, I want to display 2 perpendicular lines over my map. I had tried many examples to get an idea for that, but unfortunately, didn't succeed.
How can I make this?
And as one previous questionhere I had tried. but didn't get the answer. Can anyone guide me?
My main.xml is as following:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView android:id="#+id/main_imagemap"
android:src="#drawable/worldmap"
android:clickable="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
And my activity file(i had just started it..)
import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
public class LineMapActivity extends Activity
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView map_image = (ImageView)findViewById(R.id.main_imagemap);
}
}
And as in that link, i had also added MyImageView.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.widget.ImageView;
public class MyImageView extends ImageView
{
public MyImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
canvas.drawLine(0, 0, 20, 20, p);
super.onDraw(canvas);
}
}
Now how can i add this MyImageView to my app?
Finally I figured out a solution. It's a simple program which draws a line over an Image.
Here is my main.xml file (com.ImageDraw.MyImageView is my custom view, code below):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.ImageDraw.MyImageView android:id="#+id/main_imagemap"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
And here is the main activity:
import android.app.Activity;
import android.os.Bundle;
public class MyActivity extends Activity
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
and this is my custom image view (MyImageView):
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MyImageView extends SurfaceView implements SurfaceHolder.Callback
{
private CanvasThread canvasthread;
public MyImageView(Context context) {
super(context);
getHolder().addCallback(this);
canvasthread = new CanvasThread(getHolder(), this);
setFocusable(true);
}
public MyImageView(Context context, AttributeSet attrs)
{
super(context,attrs);
getHolder().addCallback(this);
canvasthread = new CanvasThread(getHolder(), this);
setFocusable(true);
}
protected void onDraw(Canvas canvas) {
Log.d("ondraw", "ondraw");
Paint p = new Paint();
Bitmap mapImg = BitmapFactory.decodeResource(getResources(), R.drawable.mybitmap);
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(mapImg, 0, 0, null);
p.setColor(Color.RED);
canvas.drawLine(0, 0, 100, 100, p);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
public void surfaceCreated(SurfaceHolder holder) {
canvasthread.setRunning(true);
canvasthread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
canvasthread.setRunning(false);
while (retry)
{
try
{
canvasthread.join();
retry = false;
}
catch (InterruptedException e) {
// TODO: handle exception
}
}
}
}
And finally here is my CanvasThread:
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class CanvasThread extends Thread
{
private SurfaceHolder surfaceHolder;
private MyImageView myImageView;
private boolean run = false;
public CanvasThread(SurfaceHolder s, MyImageView m)
{
surfaceHolder = s;
myImageView = m;
}
public void setRunning(boolean r)
{
run = r;
}
public void run()
{
Canvas c;
while(run)
{
c=null;
try
{
c= surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
myImageView.onDraw(c);
}
}
finally
{
if(c!=null)
{
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
You can find more details in this tutorial
Error you are getting because you are trying to casting ImageView object to MyImageView object.
Just fix the xml to include your object instead of an imageview like so (note that com.your.package.MyImageView should be the full package name of the package containing your class and then the class name)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.your.package.MyImageView android:id="#+id/main_imagemap"
android:src="#drawable/worldmap"
android:clickable="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
I have simple layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RelativeLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/backgroundtimer"
android:orientation="vertical" >
<TextView
android:id="#+id/TextView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="#string/hello" />
<com.fmech.zenclock.surface.ZenClockSurface
android:id="#+id/zenClockSurface1"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
And a have ZenClockSurface class
package com.fmech.zenclock.surface;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class ZenClockSurface extends SurfaceView implements SurfaceHolder.Callback{
private DrawClock drawClock;
public ZenClockSurface(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
getHolder().addCallback(this);
}
public ZenClockSurface(Context context) {
super(context);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
getHolder().addCallback(this);
}
public ZenClockSurface(Context context, AttributeSet attrs) {
super(context, attrs);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
getHolder().addCallback(this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
//this.getHolder().setFormat(PixelFormat.TRANSPARENT);
drawClock = new DrawClock(getHolder(), getResources());
drawClock.setRunning(true);
drawClock.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
// завершаем работу потока
drawClock.setRunning(false);
while (retry) {
try {
drawClock.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
class DrawClock extends Thread{
private boolean runFlag = false;
private SurfaceHolder surfaceHolder;
private Bitmap picture;
private Matrix matrix;
private long prevTime;
private Paint painter;
public DrawClock(SurfaceHolder surfaceHolder, Resources resources){
this.surfaceHolder = surfaceHolder;
this.surfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
picture = BitmapFactory.decodeResource(resources, R.drawable.ic_launcher);
matrix = new Matrix();
this.painter=new Paint();
this.painter.setStyle(Paint.Style.FILL);
}
public void setRunning(boolean run) {
runFlag = run;
}
#Override
public void run() {
Canvas canvas;
while (runFlag) {
matrix.preRotate(1.0f, picture.getWidth() / 2, picture.getHeight() / 2);
canvas = null;
try {
//surfaceHolder.getSurface().setAlpha(0.5f);
canvas = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(picture, matrix, this.painter);
}
}
finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
}
And code of activity
package com.fmech.zenclock.surface;
import android.app.Activity;
import android.graphics.PixelFormat;
import android.os.Bundle;
public class ZenClockSurfaceActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
setContentView(R.layout.main);
}
}
I want what background color of android picture was tranparent but i get black background.
I have background on RelativeLayout with some picture bu SurfaceView rotate Android icon with no transparent.
How i can do transparent?
Yeah, i did it i solve problem
Activity code
package com.fmech.zenclock.surface;
import android.app.Activity;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class ZenClockSurfaceActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ZenClockSurface sfvTrack = (ZenClockSurface)findViewById(R.id.zenClockSurface1);
sfvTrack.setZOrderOnTop(true); // necessary
SurfaceHolder sfhTrack = sfvTrack.getHolder();
sfhTrack.setFormat(PixelFormat.TRANSLUCENT);
}
}
Surface Code
package com.fmech.zenclock.surface;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PixelFormat;
import android.graphics.Region;
import android.util.AttributeSet;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class ZenClockSurface extends SurfaceView implements
SurfaceHolder.Callback {
private DrawClock drawClock;
public ZenClockSurface(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
getHolder().addCallback(this);
}
public ZenClockSurface(Context context) {
super(context);
getHolder().addCallback(this);
}
public ZenClockSurface(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
drawClock = new DrawClock(getHolder(), getResources());
drawClock.setRunning(true);
drawClock.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
drawClock.setRunning(false);
while (retry) {
try {
drawClock.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
class DrawClock extends Thread {
private boolean runFlag = false;
private SurfaceHolder surfaceHolder;
private Bitmap picture;
private Matrix matrix;
private Paint painter;
public DrawClock(SurfaceHolder surfaceHolder, Resources resources) {
this.surfaceHolder = surfaceHolder;
picture = BitmapFactory.decodeResource(resources,
R.drawable.ic_launcher);
matrix = new Matrix();
this.painter = new Paint();
this.painter.setStyle(Paint.Style.FILL);
this.painter.setAntiAlias(true);
this.painter.setFilterBitmap(true);
}
public void setRunning(boolean run) {
runFlag = run;
}
#Override
public void run() {
Canvas canvas;
while (runFlag) {
matrix.preRotate(1.0f, picture.getWidth() / 2,
picture.getHeight() / 2);
canvas = null;
try {
canvas = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
canvas.drawBitmap(picture, matrix, this.painter);
}
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
}
It's work.
In API 3 and 4, you cannot put anything behind a SurfaceView. Quoting Dianne Hackborn:
The surface view is actually BEHIND your window, and a hole punched in the window for you to see it. You thus can put things on top of it in your window, but nothing in your window can appear behind it.
http://groups.google.com/group/android-developers/browse_thread/thread/8d88ef9bb22da574
From API 5 onwards you can use setZOrderOnTop. The trick is that you have to do it in your constructor so it gets called before the view is attached to the window:
public ZenClockSurface(Context context, AttributeSet attrs) {
super(context, attrs);
setZOrderOnTop(true);
SurfaceHolder holder = getHolder();
holder.setFormat(PixelFormat.TRANSLUCENT);
}