I just get green Pixels at the border of my drawn bitmap if I set the alpha of the paint to 200.
The problem does not appear if I set the alpha to 100 or 255.
How can I fix this?
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
private DrawThread drawThread;
private boolean surfaceCreated;
Paint paint = new Paint();
private Bitmap bitmap;
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.circleyellow);
paint.setAlpha(200);
}
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bitmap, 200, 200, paint);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
setSurfaceCreated(true);
createDrawThread();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
setSurfaceCreated(false);
}
public void setSurfaceCreated(boolean surfaceCreated) {
this.surfaceCreated = surfaceCreated;
}
public boolean getSurfaceCreated() {
return surfaceCreated;
}
public void createDrawThread(){
if (drawThread != null) {
drawThread.destroy();
}
drawThread = new DrawThread(getHolder(), this);
drawThread.setRunning(true);
drawThread.start();
}
public DrawThread getDrawThread(){
return drawThread;
}
I think I have solved the problem. A friend has told me this solution:
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
getHolder().setFormat(PixelFormat.TRANSLUCENT);
bitmap = BitmapFactory.decodeResource(
getResources(),
R.drawable.circleyellow
);
paint.setAlpha(200);
}
Related
I have created a class from SurfaceView.I wanted it that when i touch on the screen then the screen will be refreshed by calling invalidate() function. But in my implementation invalidate () is not called when i touched on the screen.
Here is my code.
public class GameBoard extends SurfaceView implements Callback {
private SurfaceHolder holder;
int clicked =0;
public GameBoard(Context context)
{
super(context);
holder = getHolder();
holder.addCallback(this);
setFocusable(true);
requestFocus();
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
Canvas c = holder.lockCanvas(null);
onDraw(c);
holder.unlockCanvasAndPost(c);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
// TODO Auto-generated method stub
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
}
public boolean onTouchEvent(MotionEvent event)
{
int action = event.getAction();
if (action==MotionEvent.ACTION_UP)
{
clicked++;
// Canvas c = holder.lockCanvas(null);
// onDraw(c);
// holder.unlockCanvasAndPost(c);
invalidate();
}
return true;
}
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawColor(0xFF00ff00);
Paint p = new Paint();
p.setTextSize(20);
p.setColor( Color.RED );
p.setAntiAlias(true);
canvas.drawText(""+clicked, 100, 500, p);
}
}
I have an android application showing coverflow animation.I want to use view extending surfaceview inside coverflow.But this code did not show anything.
public class CoverFlowView extends SurfaceView implements Callback {
public CoverFlowView(Context context) {
super(context);
}
public CoverFlowView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CoverFlowView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
public void surfaceCreated(SurfaceHolder holder) {
MyThread myThread = new MyThread(holder);
myThread.setFlag(true);
myThread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint borderPaint = new Paint();
borderPaint.setARGB(255, 255, 128, 0);
borderPaint.setStyle(Paint.Style.STROKE);
borderPaint.setStrokeWidth(4);
canvas.drawRect(0, 0, getWidth() - 1, getHeight() - 1, borderPaint);
}
class MyThread extends Thread {
boolean flag;
SurfaceHolder myHolder;
public MyThread(SurfaceHolder holder) {
myHolder = holder;
}
public void setFlag(boolean myFlag) {
flag = myFlag;
}
public void run() {
Canvas canvas = null;
while (flag) {
try {
canvas = myHolder.lockCanvas();
synchronized (myHolder) {
invalidate();
}
} finally {
if (canvas != null) {
myHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
}
What is the problem here?I am new with Surfaceview.
Thanks in advance.
Rewrite your code like this , then it will work fine, i have checked it
public class CoverFlowView extends SurfaceView implements SurfaceHolder.Callback {
then change your constructor to
public CoverFlowView(Context context) {
super(context);
getHolder().addCallback(this);
}
I am trying to click a button and add a resistor. So what I need is to invalidate the view when the button is clicked. But the invalidate that is inside MyView inside the method update() is not working. I have been trying to search for this problem but I have found nothing similar to what I am trying to do, or maybe this is not the way to do it.
DefaultActivity.java
public class DefaulActivity extends Activity {
MyView myView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myView = new MyView(this, null);
final Button bAddResistor = (Button) findViewById(R.id.bAdd);
bAddResistor.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
myView.update();
Log.d("ButtonADD", "Button Add has been clicked");
}
});
}
}
MyView.java
public class MyView extends SurfaceView implements SurfaceHolder.Callback{
Resistor myResistor;
private ArrayList<Resistor> mElements = new ArrayList<Resistor>();
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
synchronized (mElements) {
for (Resistor element : mElements) {
element.doDraw(canvas);
}
}
}
public void update() {
mElements.add(new Resistor(getContext(), (int) 10, (int) 10));
invalidate(); //Does not work!
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas c = holder.lockCanvas();
onDraw(c);
holder.unlockCanvasAndPost(c);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
Resistor.java
public class Resistor extends View{
private Path mSymbol;
private Paint mPaint;
private int mX;
private int mY;
//...Override Constructors...
public Resistor(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public Resistor(Context context, int x, int y){
super(context);
mX = x;
mY = y;
init();
}
private void init() {
mSymbol = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(2);
mPaint.setColor(-7829368);
mPaint.setStyle(Paint.Style.STROKE);
//...Your code here to set up the path,
//...allocate objects here, never in the drawing code.
mSymbol.moveTo(0.0F, 0.0F);
mSymbol.lineTo(0.0F, 50.0F);
mSymbol.lineTo(16.666666F, 58.333332F);
mSymbol.lineTo(-16.666666F, 75.0F);
mSymbol.lineTo(16.666666F, 91.666664F);
mSymbol.lineTo(-16.666666F, 108.33333F);
mSymbol.lineTo(16.666666F, 124.99999F);
mSymbol.lineTo(-16.666666F, 141.66666F);
mSymbol.lineTo(0.0F, 150.0F);
mSymbol.lineTo(0.0F, 200.0F);
mSymbol.offset(mX, mY);
}
public void doDraw(Canvas canvas) {
canvas.drawPath(mSymbol, mPaint);
}
You should use a ViewGroup instead of a SurfaceView. Add the Resistor-Views as children to MyView, measure and layout them appropriately and the ViewGroup will automatically take care of drawing them.
SurfaceView requires you to do your drawing in a seperate thread. You have to start that thread in surfaceCreated and keep redrawing the view as needed. For simple views like the one you posted it is perfectly acceptable to just do your drawing in the UI thread. No SurfaceView required.
I haven't used Surfaceviews before but if you in the API you can see, that there is no function called "invalidate()" for the SurfaceView class.
Maybe you can manage to re-use this line somehow:
holder.unlockCanvasAndPost(c);
I am trying an example having SurfaceView. I have inherited my class from SurfaceView and using as follows:
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
Context context;
MySurfaceViewThread mThread;
SurfaceHolder holder;
Paint paint;
int x = 20, y = 20, r = 10;
public void init() {
holder = getHolder();
holder.addCallback(this);
mThread = new MySurfaceViewThread(getHolder(), this);
paint = new Paint();
paint.setStyle(Style.STROKE);
paint.setStrokeCap(Cap.ROUND);
paint.setStrokeWidth(1);
paint.setColor(Color.rgb(255, 255, 255));
}
public MySurfaceView(Context context) {
super(context);
// TODO Auto-generated constructor stub
this.context = context;
init();
}
public MySurfaceView(Context context, AttributeSet attr) {
super(context,attr);
this.context = context;
init();
}
public MySurfaceView(Context context, AttributeSet attr, int defStyle) {
super(context, attr, defStyle);
this.context = context;
init();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
mThread.isRunning = false;
while (true) {
try {
mThread.join();
break;
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public void onDraw(Canvas canvas) {
// super.onDraw(canvas);
// canvas.drawColor(0, Mode.CLEAR);
x += 2;
y += 2;
r += 3;
canvas.drawColor(Color.rgb(x%255, y%255, (x+y)%255));
canvas.drawCircle(x, y, r, paint);
canvas.drawText("x:"+x, 100, 100, paint);
Log.d("onDraw","onDraw()"+"x:"+x + ",y:"+y+",r:"+r);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
Log.d("surfaceCreated", "surfaceCreated()");
mThread.isRunning = true;
mThread.start();
}
}
I am updating my Canvas from a Thread which is:
public class MySurfaceViewThread extends Thread {
SurfaceHolder holder;
MySurfaceView surfaceView;
boolean isRunning = false;
public MySurfaceViewThread(SurfaceHolder holder, MySurfaceView surfaceView) {
Log.d("thread","thread constructor");
this.holder = holder;
this.surfaceView = surfaceView;
}
#Override
public void run() {
Log.d("run","run()");
while(isRunning) {
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
synchronized(holder) {
surfaceView.onDraw(canvas);
}
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
holder.unlockCanvasAndPost(canvas);
Log.d("canvas status", "canvas unlocaked...");
}
}
}
}
When application starts and its onDraw() is called, it draws circle and text as well but on further calls to onDraw() it draws nothing. Means nothing changed on screen after first update. Any idea where I am getting wrong? I am new to android and slow learner as well.
I got the answer. Its very strange. I don't know why this worked.
I commented the following line from my activity and it runs.
surfaceView.setBackgroundColor(Color.rgb(0, 255, 0));
the activity code is:
public class SurfaceViewTutorialActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MySurfaceView surfaceView = new MySurfaceView(this);
// surfaceView.setBackgroundColor(Color.rgb(0, 255, 0));
surfaceView.setBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));
setContentView(surfaceView);
}
}
If any one knows about this, kindly guide me to the right direction.
Hi i draw a canvas for my application
here is the code my canvas
public class Canvas1 extends View{
int i;
int k;
float l,m;
public Canvas1(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public Canvas1 (Context context, AttributeSet attrs) {
super(context, attrs);
}
public Canvas1 (Context context, AttributeSet ats, int ds) {
super(context, ats, ds);
}
#Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawRGB(255, 255, 255);
Paint paint1=new Paint(Color.BLACK);
Paint paint=new Paint(200);
paint.setStrokeWidth((float)0.5);
canvas.drawLine(0,0,0,getMeasuredHeight(), paint1);
canvas.drawLine(0,0, getMeasuredWidth(), 0, paint1);
canvas.drawLine(0,getMeasuredHeight(), getMeasuredWidth(),getMeasuredHeight(), paint1);
canvas.drawLine(getMeasuredWidth(),getMeasuredHeight(), getMeasuredWidth(), 0, paint1);
//canvas.drawLine(0, 0, ((float)getMeasuredWidth()), ((float)getMeasuredHeight()), paint);
if(l!=0||m!=0)
{
canvas.drawLine(getMeasuredWidth()/2,getMeasuredHeight()/2,getMeasuredWidth()/2,getMeasuredHeight(),paint);
canvas.drawLine(0,0,getMeasuredWidth()/2,getMeasuredHeight()/2,paint);
}
for(int i=1;i<5;i++)
canvas.drawLine(((float)getMeasuredWidth())/5*i, 0, ((float)getMeasuredWidth()/5*i),getMeasuredHeight(), paint);
for(int i=0;i<5;i++)
canvas.drawLine(0, getMeasuredHeight()/5*i, getMeasuredWidth(), getMeasuredHeight()/5*i, paint);
canvas.save();
}
public Boolean setline(float d,float e){
l=d;
m=e;
Log.i("Hello Canvas",l+" "+m+" ");
return true;
}
}
now i am trying to call the function setline() from my main activity in this activity there is an array of canvas . here is the code of my activity
public class HelloCanvasActivity extends Activity {
/** Called when the activity is first created. */
Integer[] in={R.id.can1,R.id.can2,R.id.can3,R.id.can4,R.id.can5,R.id.can6,R.id.can7,R.id.can8};
float x,y;
int j=0;
Canvas1[] can=new Canvas1[8];
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
for(int i=0;i<8;i++)
{
can[i]=(Canvas1)findViewById(in[i]);
}
can[0].setline((float)0.5,(float) 0.5);
new Thread(new Runnable(){
public void run(){
for(int i=0;i<8;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
can[i].setline((float)0.5,(float)0.5);
}
}
}).start();
}
}
when i omit Thread.sleep(1000) from my code lines are drawing but when i put Thread.sleep(1000) setline is calling after 1 second i am getting log in my log table of Hello World,but no line is drawing on canvas please help me in finding where i am wrong.
In your setline method, call invalidate()