Surfaceview to draw Thread error NULLPointerException - java

I'm a beginner in android. I'm creating a simple surface view to draw a thread (draw rectangle), but it keeps getting error like this :
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawColor(int)' on a null object reference
and this is my code :
myActivity.java :
public class myActivity extends AppCompatActivity {
mySurfaceView mysurfaceview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ball);
//mysurfaceview = new mySurfaceView(this);
mysurfaceview = (mySurfaceView) findViewById(R.id.mySurfaceView);
mysurfaceview.RunThread();
}
mySurfaceview.java :
public class mySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
public DrawThread DrawThread;
private Rect myrectangle;
private Paint myPaint;
int moveX = 0;
private void init() {
myrectangle = new Rect(150, 150, 700, 500);
myPaint = new Paint();
myPaint.setColor(Color.BLUE);
}
public mySurfaceView(Context context) {
super(context);
//init();
}
public mySurfaceView(Context context, AttributeSet attrs, int defStyle){ super(context, attrs, defStyle); }
public mySurfaceView(Context context, AttributeSet attrs) { super(context, attrs); }
public void onDrawSomething(Canvas canvas) {
canvas.drawColor(Color.BLACK);
canvas.drawRect(myrectangle, myPaint);
}
#Override
public void surfaceCreated(SurfaceHolder holder) { }
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
#Override
public void surfaceDestroyed(SurfaceHolder holder) { }
public void update(){
}
public void RunThread() {
init();
DrawThread = new DrawThread(getHolder(), this);
DrawThread.setRunning(true);
DrawThread.start();
}
public class DrawThread extends Thread {
//var definition
public boolean run = false;
private SurfaceHolder surfaceHolder;
mySurfaceView mysurfaceView;
public DrawThread(SurfaceHolder surfaceHolder, mySurfaceView mysurfaceView) {
this.surfaceHolder = surfaceHolder;
this.mysurfaceView = mysurfaceView;
}
public void setRunning(boolean run) {
this.run = run;
}
#Override
public void run() {
while(run)
{
//implement fps counter
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
mysurfaceView.onDrawSomething(canvas);
//mysurfaceView.update();
}
} finally {
if(canvas != null)
{
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
}
And this is my XML code to show surface view :
<com.example.firstapp_aurelia.mySurfaceView
android:id="#+id/mySurfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Did I do anything wrong here? Thank you so much.

I didn't run you code but do not initial mySurfaceView twice
mysurfaceview = new mySurfaceView(this);
mysurfaceview = (mySurfaceView) findViewById(R.id.mySurfaceView);

Related

Android Studio Changing brush sizes

In my Application if the brush size is selected it changes the brush size but it also changes the size of the brush inside the canvas how to make it so that the brush size inside the canvas doesn't change.
This is my code for the EasyOne.Java - This contains contain the brushsizes:
import static com.example.artbit.display2.colorList1;
import static com.example.artbit.display2.currentbrush1;
import static com.example.artbit.display2.pathlist1;
public class EasyOne extends AppCompatActivity {
public static Path path1 = new Path();
public static Paint paintbrush1 = new Paint();
public static String brushsize1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_easy_one);
This is for the brushes
public void SmallBrush1(View view){
paintbrush1.setStrokeWidth(10f);
paintbrush1.setColor(Color.BLACK);
currentColor1(paintbrush1.getColor());
}
public static void BigBrush1(View view){
/* brushsize1 = "1";
paintbrush1.setColor(Color.BLACK);
currentColor1(paintbrush1.getColor());*/
paintbrush1.setStrokeWidth(50f);
currentColor1(paintbrush1.getColor());
}
public void Brush1(View view) {
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.selecttools);
mediaPlayer.start();
paintbrush1.setStrokeWidth(20f);
paintbrush1.setColor(Color.BLACK);
currentColor1(paintbrush1.getColor());
}
public void Clear1(View view){
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.selecttools);
mediaPlayer.start();
pathlist1.clear();
path1.reset();
colorList1.clear();
}
public static void currentColor1 (int c){
currentbrush1 = c;
path1 = new Path();
}
public static void currentsizebrush1(int c){
currentbrush1 = c;
path1 = new Path();
}
}
and this is the code for display which is the canvas this contains the pathlist and arrays for colors
import static com.example.artbit.EasyOne.paintbrush1;
import static com.example.artbit.EasyOne.path1;
import static com.example.artbit.EasyOne.brushsize1;
import android.graphics.Paint;
import android.graphics.Path;
public class display2 extends View {
public static MediaPlayer player;
public static ArrayList<Path> pathlist1 = new ArrayList<>();
public static ArrayList<Path> pathlist2 = new ArrayList<>();
public static ArrayList<Integer> brushList1 = new ArrayList<>();
public static ArrayList<Integer> colorList1 = new ArrayList<>();
public ViewGroup.LayoutParams params;
public static int currentbrush1 = Color.BLACK;
public display2(Context context) {
super(context);
init(context);
}
public display2(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public display2(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context){
paintbrush1.setAntiAlias(true);
paintbrush1.setColor(Color.BLACK);
paintbrush1.setStyle(Paint.Style.STROKE);
paintbrush1.setStrokeCap(Paint.Cap.ROUND);
paintbrush1.setStrokeJoin(Paint.Join.ROUND);
paintbrush1.setStrokeWidth(10f);
params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
path1.moveTo(x,y);
invalidate();
return true;
case MotionEvent.ACTION_MOVE:
path1.lineTo(x,y);
pathlist1.add(path1);
colorList1.add(currentbrush1);
brushList1.add(currentbrush1);
invalidate();
return true;
default:
return false;
}
}
#Override
protected void onDraw(android.graphics.Canvas canvas) {
for (int i=0; i<pathlist1.size(); i++){
paintbrush1.setColor(colorList1.get(i));
paintbrush1.setStrokeWidth(brushList1.get(i));
canvas.drawPath(pathlist1.get(i),paintbrush1);
invalidate();
}
}
}
I think I figured out the problem, the problem is in your onTouchEvent at
brushList1.add(currentbrush1);
You are adding to the ArrayList of brush's size the Color of the Path which is Black by default is -16777216 so when in draw you set the strokeWidth to a negative value it uses the Paint current value. So create a static int strokeWidth inside display2 and add to all your brush methods strokeWidth = //width number; like so
public void SmallBrush1(View view){
paintbrush1.setStrokeWidth(10f);
strokeWidth = 10; //ADD THIS
paintbrush1.setColor(Color.BLACK);
currentColor1(paintbrush1.getColor());
}
Do for all your brush methods
So change this
brushList1.add(currentbrush1);
to
brushList1.add(strokeWidth);
this should fix your problem
Hope that helps

SurfaceView shows black screen except icon

I used the old guide according to which the icon should appear in surfaceview.
Unfortunately the app dispalys the entire black surfaceview except icon.
I do not
know how to fix this because android studio does not display errors.
What i should add or change?
public class mySurfaceView extends SurfaceView {
private SurfaceHolder surfaceHolder;
private Bitmap bmpIcon;
public mySurfaceView(Context context) {
super(context);
init();
}
public mySurfaceView(Context context,
AttributeSet attrs) {
super(context, attrs);
init();
}
public mySurfaceView(Context context,
AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init(){
surfaceHolder = getHolder();
bmpIcon = BitmapFactory.decodeResource(getResources(),
R.drawable.icon);
surfaceHolder.addCallback(new SurfaceHolder.Callback(){
#Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas canvas = holder.lockCanvas(null);
drawSomething(canvas);
holder.unlockCanvasAndPost(canvas);
}
#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
}});
}
protected void drawSomething(Canvas canvas) {
canvas.drawColor(Color.BLACK);
if (bmpIcon != null){ canvas.drawBitmap(bmpIcon,
getWidth()/2, getHeight()/2, null);
}
}
}
ScreenShot
my icon
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF020000"
android:pathData="M6,18c0,0.55 0.45,1 1,1h1v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L11,19h2v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L16,19h1c0.55,0 1,-0.45 1,-1L18,8L6,8v10zM3.5,8C2.67,8 2,8.67 2,9.5v7c0,0.83 0.67,1.5 1.5,1.5S5,17.33 5,16.5v-7C5,8.67 4.33,8 3.5,8zM20.5,8c-0.83,0 -1.5,0.67 -1.5,1.5v7c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5v-7c0,-0.83 -0.67,-1.5 -1.5,-1.5zM15.53,2.16l1.3,-1.3c0.2,-0.2 0.2,-0.51 0,-0.71 -0.2,-0.2 -0.51,-0.2 -0.71,0l-1.48,1.48C13.85,1.23 12.95,1 12,1c-0.96,0 -1.86,0.23 -2.66,0.63L7.85,0.15c-0.2,-0.2 -0.51,-0.2 -0.71,0 -0.2,0.2 -0.2,0.51 0,0.71l1.31,1.31C6.97,3.26 6,5.01 6,7h12c0,-1.99 -0.97,-3.75 -2.47,-4.84zM10,5L9,5L9,4h1v1zM15,5h-1L14,4h1v1z"/>
</vector>
You gave black color in drawSomething method, If you change the color your background will change.
protected void drawSomething(Canvas canvas) {
//canvas.drawColor(Color.BLACK);
canvas.drawColor(Color.RED); // here i changed black to red(add you expected color here)
if (bmpIcon != null) {
canvas.drawBitmap(bmpIcon,
getWidth() / 2, getHeight() / 2, null);
}
}
As your drawble is vector drawable so use the following function to convert into bitmap
public static Bitmap getBitmapFromVectorDrawable(Context context, int drawableId) {
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
drawable = (DrawableCompat.wrap(drawable)).mutate();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
and create your bitmap like this
bmpIcon = getBitmapFromVectorDrawable(getContext(), R.drawable.icon);
it will work fine.
and your final code will be like this,
public class MySurface extends SurfaceView {
private SurfaceHolder surfaceHolder;
private Bitmap bmpIcon;
public MySurface(Context context) {
super(context);
init();
}
public MySurface(Context context,
AttributeSet attrs) {
super(context, attrs);
init();
}
public MySurface(Context context,
AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public static Bitmap getBitmapFromVectorDrawable(Context context, int drawableId) {
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
drawable = (DrawableCompat.wrap(drawable)).mutate();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
private void init() {
surfaceHolder = getHolder();
bmpIcon = getBitmapFromVectorDrawable(getContext(), R.drawable.icon);
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas canvas = holder.lockCanvas(null);
drawSomething(canvas);
holder.unlockCanvasAndPost(canvas);
}
#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
}
});
}
protected void drawSomething(Canvas canvas) {
canvas.drawColor(Color.RED);
if (bmpIcon != null) {
canvas.drawBitmap(bmpIcon,
getWidth() / 2, getHeight() / 2, null);
}
}
}

OnClickListener not triggered inside Fragment

I have custom class (ActionBar.class) where I implemented custom ActionBar component with OnClickListener (OnBackButtonClickListener).When I call this method in my fragment, it does not get triggered.
Here is my custom class:
public class ActionBar extends LinearLayout {
private boolean showBackButton;
private boolean showXButton;
private boolean showHeader;
private String header = "";
private OnClickListener onBackButtonClickListener;
private OnClickListener onXButtonClickListener;
#Bind(R.id.back) ImageView backButton;
#Bind(R.id.header) AutoResizeTextView headerText;
#Bind(R.id.x_btn) ImageView xButton;
public ActionBar(Context context) {
super(context);
initialize(context, null);
}
public ActionBar(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context, attrs);
}
public ActionBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context, attrs);
}
public ActionBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize(context, attrs);
}
private void initialize(Context context, AttributeSet attributeSet) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.action_bar_layout, this);
ButterKnife.bind(this, view);
if(attributeSet != null) {
TypedArray typedArray =
context.getTheme().obtainStyledAttributes(attributeSet, R.styleable.ActionBar, 0, 0);
try {
setHeader(typedArray.getString(R.styleable.ActionBar_header) == null ?
"" : typedArray.getString(R.styleable.ActionBar_header));
setShowBackButton(typedArray.getBoolean(R.styleable.ActionBar_show_back_button, false));
setShowXButton(typedArray.getBoolean(R.styleable.ActionBar_show_x_button, false));
setShowHeader(typedArray.getBoolean(R.styleable.ActionBar_show_header, false));
} finally {
typedArray.recycle();
}
}
}
public boolean isShowBackButton() {
return showBackButton;
}
public void setShowBackButton(boolean showBackButton) {
this.showBackButton = showBackButton;
invalidate();
requestLayout();
}
public boolean isShowXButton() {
return showXButton;
}
public void setShowXButton(boolean showXButton) {
this.showXButton = showXButton;
invalidate();
requestLayout();
}
public boolean isShowHeader() {
return showHeader;
}
public void setShowHeader(boolean showHeader) {
this.showHeader = showHeader;
invalidate();
requestLayout();
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
invalidate();
requestLayout();
}
public OnClickListener getOnBackButtonClickListener() {
return onBackButtonClickListener;
}
public void setOnBackButtonClickListener(OnClickListener onBackButtonClickListener) {
this.onBackButtonClickListener = onBackButtonClickListener;
}
public OnClickListener getOnXButtonClickListener() {
return onXButtonClickListener;
}
public void setOnXButtonClickListener(OnClickListener onXButtonClickListener) {
this.onXButtonClickListener = onXButtonClickListener;
}
#Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
backButton.setVisibility(showBackButton ? VISIBLE : INVISIBLE);
xButton.setVisibility(showXButton ? VISIBLE : INVISIBLE);
headerText.setVisibility(showHeader ? VISIBLE : INVISIBLE);
headerText.setText(header);
}
#OnClick(R.id.x_btn) void onXButtonClick(View v) {
if(getOnBackButtonClickListener() != null) {
getOnBackButtonClickListener().onClick(v);
}
}
#OnClick(R.id.back) void onBackButtonClick(View v) {
if(getOnXButtonClickListener() != null) {
getOnXButtonClickListener().onClick(v);
}
}
}
Here is my Fragment and method setOnBackButtonClickListener call:
public class ForgotPasswordFragment extends BasePagerFragment
implements ForgotPasswordView, TextView.OnEditorActionListener, ActionBar.OnClickListener{
#Bind(R.id.action_bar) ActionBar actionBar;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
actionBar.setOnBackButtonClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
navigateTo(LoginActivity.class);
}
});
}
You have
#OnClick(R.id.x_btn) void onXButtonClick(View v) {
if(getOnBackButtonClickListener() != null) {
getOnBackButtonClickListener().onClick(v);
}
}
#OnClick(R.id.back) void onBackButtonClick(View v) {
if(getOnXButtonClickListener() != null) {
getOnXButtonClickListener().onClick(v);
}
}
But it looks like it should be:
#OnClick(R.id.back) void onXButtonClick(View v) {
if(getOnBackButtonClickListener() != null) {
getOnBackButtonClickListener().onClick(v);
}
}
#OnClick(R.id.x_btn) void onBackButtonClick(View v) {
if(getOnXButtonClickListener() != null) {
getOnXButtonClickListener().onClick(v);
}
}
Use #Onclick(R.id.action_bar) void methodNAme()
{
//ToDo
}

Android Canvas always drawing a blackscreen

i've a problem canvas always draw a black screen no matter what i want to draw.
no matter when i want that the contentview is the View class or i take a layout and
add the class or i let the canvas draw a background and so on
public class GameSurface extends SurfaceView {
private SurfaceHolder holder;
GameThread gameThread;
Bitmap background;
public GameSurface(Context context) {
super(context);
holder = getHolder();
gameThread = new GameThread(this);
background = BitmapFactory.decodeResource(getResources(), R.drawable.background1);
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
gameThread.setRunning(true);
gameThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameThread.setRunning(false);
while (retry){
try {
gameThread.join();
retry = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(background,0,0,new Paint());
}
}
Rebuild and clean brings nothing!
Whats the Problem?
Thank You!

ClickListener and TouchListener don't work on a child view

I have 2 custom Views: 1. BoardView 2. BallView. I add The BallView to the BoardView and the BoardView to my layout.
When I click on the BallView with ClickListener and TouchListener nothing happens. As if the BoardView overlaps the BallView area.
Code:
board = new BoardView(this);
ball = new BallModel(100, 200,50,screenWidth, screenHeight);
ballView = new BallView(this, ball);
ballView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event)
{
System.out.println("Hey");
return true;
}
});
ballView.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
System.out.println("Hey");
}
});
board.addView(ballView);
Updated:
public class BoardView extends View
{
private List<View> mShapes = new ArrayList<View>();
public BoardView(Context context)
{
super(context);
}
public void addView(View view)
{
mShapes.add(view);
}
#Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
for(int i=0; i<mShapes.size(); i++)
{
View view = mShapes.get(i);
view.draw(canvas);
}
}
}
public class BallView extends View
{
BallModel mBall;
Paint mBallPaint;
public BallView(Context context, BallModel ball)
{
super(context);
mBall = ball;
}
private Paint getPaint()
{
if(mBallPaint == null)
{
mBallPaint = new Paint();
mBallPaint.setColor(mBall.getColor());
}
return mBallPaint;
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint paint = getPaint();
paint.setColor(mBall.getColor());
canvas.drawCircle(mBall.getX(), mBall.getY(), mBall.getRadius(), paint);
}
}
Any ideas?

Categories

Resources