The question of Android SurfaceView.
I want to draw a Circle in SurfaceView ,but canvas is null in SimpleDraw method.Why?
No 1 ,canvas is null.
No 2,SimpleDraw method run in ClickListener,is right , canvas is not null,why?
1.public class SurfaceTestActivity extends Activity {
SurfaceView sfv;
SurfaceHolder sfh;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
sfv=(SurfaceView)findViewById(R.id.surface);
sfh=sfv.getHolder();
SimpleDraw();
}
void SimpleDraw(){
Canvas canvas = sfh.lockCanvas(new Rect(0, 0, 300,
getWindowManager().getDefaultDisplay().getHeight()));
Paint mPaint = new Paint();
mPaint.setColor(Color.GREEN);
mPaint.setStrokeWidth(2);
canvas.drawCircle(150, 150, 80, mPaint);
sfh.unlockCanvasAndPost(canvas);
}
}
2.public class SurfaceTestActivity extends Activity {
Button simpleButton;
SurfaceView sfv;
SurfaceHolder sfh;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
simpleButton=(Button)findViewById(R.id.simple);
sfv=(SurfaceView)findViewById(R.id.surface);
sfh=sfv.getHolder();
simpleButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//SimpleDraw();
}
});
}
void SimpleDraw(){
Canvas canvas = sfh.lockCanvas(new Rect(0, 0, 300,
getWindowManager().getDefaultDisplay().getHeight()));
Paint mPaint = new Paint();
mPaint.setColor(Color.GREEN);
mPaint.setStrokeWidth(2);
canvas.drawCircle(150, 150, 80, mPaint);
sfh.unlockCanvasAndPost(canvas);
}
}
The difference is timing.
No. 1 Tries to draw to the canvas before it is created and fails. The call to sfh.lockCanvas(...) fails and returns null, not the Canvas.
No. 2 Tries to draw after the canvas has been created, so it works.
Do this:
public class SurfaceTestActivity extends Activity implements SurfaceHolder.Callback {
SurfaceView sfv;
SurfaceHolder sfh;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
sfv=(SurfaceView)findViewById(R.id.surface);
sfh=sfv.getHolder();
sfh.addCallback(this);
}
void SimpleDraw(){
Canvas canvas = sfh.lockCanvas(new Rect(0, 0, 300,
getWindowManager().getDefaultDisplay().getHeight()));
Paint mPaint = new Paint();
mPaint.setColor(Color.GREEN);
mPaint.setStrokeWidth(2);
canvas.drawCircle(150, 150, 80, mPaint);
sfh.unlockCanvasAndPost(canvas);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// draw AFTER surface created!
simpleDraw();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
CHANGES:
adding SurfaceHolder.Callback
adding sfh.addCallback(this);
adding 3 #Override methods with new SimpleDraw -- after the canvas is created.
Related
My application requires to post data to a custom view and redraw the view according to sent data from MainActivity.
Here are sample code.
Custom view->
public class custom_view extends View {
private simple_line line;
public custom_view(Context context) {
super(context);
line=new simple_line(0);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
line.draw_line(canvas);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(),getMeasuredHeight());
}
private class simple_line{
private float x_val;
private Paint mpaint;
public simple_line(float val){
x_val=val;
mpaint=new Paint();
mpaint.setColor(Color.RED);
mpaint.setStyle(Paint.Style.STROKE);
mpaint.setStrokeWidth(10);
}
public float getX_val() {
return x_val;
}
public void setX_val(float x_val) {
this.x_val = x_val;
invalidate();
}
public void draw_line(Canvas canvas){
Path mpath=new Path();
mpath.moveTo(getWidth()/2+x_val,0);
mpath.lineTo(getWidth()/2+x_val,getHeight());
mpath.close();
canvas.drawPath(mpath,mpaint);
}
}
public void update_xval(float val){
line.setX_val(val);
}
}
Here is Main activity->
public class MainActivity extends AppCompatActivity{
private Button button;
private custom_view myview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button)findViewById(R.id.mybutton);
myview=(custom_view)findViewById(R.id.myview);
myview=new custom_view(this);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myview.update_xval(100);
}
});
}
}
I am unable to update x_val when button is pressed.Where am I going wrong.What needs to be done to update x_val?
there is an issue in draw_line(Canvas canvas) function. you are not calling this function in custom_view. you need to invalidate() after draw_line(Canvas canvas)called.
I am trying to make a match 3 game. For starters, I wanted to draw something on the screen, but no matter what I try, I get just a black screen.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//MAKE FULLSCREEN
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
GameView gameview = new GameView(this);
setContentView(gameview);
}
}
public class GameView extends SurfaceView{
private int numCol, numRow;
private int bWid, bHeight;
private Bitmap purpleBit;
private Bitmap rainbowBitmp;
private Bitmap redBitmp;
public GameView(Context context){
super(context);
}
#Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setColor(Color.rgb(250, 0, 0));
canvas.drawRect(100, 100, 200, 200, paint);
}
}
Set the paint width, color, stroke
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//MAKE FULLSCREEN
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
GameView gameview = new GameView(this);
setContentView(gameview);
}
}
public class GameView extends SurfaceView{
private int numCol, numRow;
private int bWid, bHeight;
private Bitmap purpleBit;
private Bitmap rainbowBitmp;
private Bitmap redBitmp;
public GameView(Context context){
super(context);
}
#Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
Paint mPaint = new Paint();
//this is missing
mPaint.setColor(Color.rgb(250, 0, 0));
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(10);
canvas.drawRect(100, 100, 200, 200, mPaint);
}
}
I'm trying to make an app that draws a circle on a bitmap. Right now, I have a button that produces the circle. Instead, I would like to draw the circle where the user double-taps (instead of pressing a button). How can I do this programmatically? Here is the content of the activity so far:
public static final String KEY_PATH = "img.jpg";
private ZoomInZoomOut touch;
private Bitmap bitmap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_display);
Intent intent = getIntent();
String path = getIntent().getStringExtra(ImageDisplayActivity.KEY_PATH);
try {
java.io.FileInputStream in = this.openFileInput(path);
bitmap = BitmapFactory.decodeStream(in);
bitmap = bitmap.copy(bitmap.getConfig(), true);
touch = (ZoomInZoomOut)findViewById(R.id.IMAGEID);
touch = arrangeImageView(touch);
touch.setImageBitmap(bitmap);
in.close();
Button draw = (Button) findViewById(R.id.draw);
draw.setOnClickListener(new View.OnClickListener(){
public void onClick(View v)
{
Bitmap bmOverlay = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(),
bitmap.getConfig());
Canvas canvas = new Canvas(bmOverlay);
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.BLUE);
p.setStrokeWidth(2);
p.setStyle(Paint.Style.STROKE);
canvas.drawBitmap(bitmap,new Matrix(),null);
canvas.drawCircle(1000, 1000, 20, p);
touch.setImageBitmap(bmOverlay);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
You have to implement GestureDetector and put your code in single/double click. Here you can replace button with bitmap.
TestActivity.java
iv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//putyour first activity call.
}
}
iv.setOnTouchListener(new OnTouchListener() {
GestureDetector gestureDetector = new GestureDetector(new MyGestureDetector(context));
#Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
Now you have to create GestureDetector.java class.
public class MyGestureDetector extends SimpleOnGestureListener {
public Context context;
public String phno;
public MyGestureDetector(Context con)
{
this.context=con;
}
#Override
public boolean onDown(MotionEvent e) {
return super.onDown(e);
}
public MyGestureDetector(Context con) {
this.context=con;
}
#Override
public boolean onDoubleTap(MotionEvent e) {
System.out.println("in Double tap");
return true;
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
System.out.println("in single tap up");
//put your second activity.
return super.onSingleTapUp(e);
}
}
I am new to android. Sorry if this question is very silly...
I am trying to create a simple app.
The rule is .. whenever i touch or click a button which is located at the center, the radius of circle should get increased. And whenever i stopped clicking , then the radius of the circle should be reduced slowly. Here i created a circle, but i can't update it. I used button click listner and onTouchListner but nothing works... Please help me to do this app... Thank you so much for your help..
public class TestcircleActivity extends Activity {
/** Called when the activity is first created. */
Button b;
int clicks = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
}
public class MyView extends View implements OnTouchListener {
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
int x = getWidth();
int y = getHeight();
int radius;
radius = 100;
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.WHITE);
canvas.drawPaint(paint);
// Use Color.parseColor to define HTML colors
paint.setColor(Color.parseColor("#CD5C5C"));
canvas.drawCircle(x / 2, y / 2, radius, paint);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
}
}
I am using Eclipse to write an Android app. I want my app to display a background image which is stretched to the size of the screen.
I have written the following code, but in the emulator it immediately exited the app when I ran it. Could someone please help me to understand the problem...
Here is my code...
public class Roller extends Activity {
Display display = getWindowManager().getDefaultDisplay();
int dwidth = display.getWidth();
int dheight = display.getHeight();
Bitmap background1 = BitmapFactory.decodeResource(getResources(),R.drawable.sunnybackground);
Bitmap BSunny = Bitmap.createScaledBitmap(background1,dwidth,dheight,true);
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new Panel(this));
}
class Panel extends View {
public Panel(Context context) {
super(context);
}
public void onDraw(Canvas canvas) {
canvas.drawBitmap(BSunny, 0, 0, null);
}
}
}
Why not just something like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
ImageView iv = new ImageView(this, null);
iv.setBackgroundResource(R.drawable.sunnybackground);
setContentView(iv);
}
Why don't you set the background image in the layout xml file?
Do you have to set it programmatically at runtime?
I think you do as below
(It seems that you can't get display info unless activity is created)
public class Roller extends Activity {
Bitmap BSunny;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
Display display = getWindowManager().getDefaultDisplay();
int dwidth = display.getWidth();
int dheight = display.getHeight();
Bitmap background1 = BitmapFactory.decodeResource(getResources(),R.drawable.sunnybackground);
BSunny = Bitmap.createScaledBitmap(background1,dwidth,dheight,true);
setContentView(new Panel(this));
}
class Panel extends View {
public Panel(Context context) {
super(context);
}
public void onDraw(Canvas canvas) {
canvas.drawBitmap(BSunny, 0, 0, null);
}
}
}