Android: How do I make a scrollable Canvas? - java

I am writing an app. One aspect of it is lines being drawn over an image. Here's the practice code I've been working with:
public class DrawView extends View {
Paint paint = new Paint();
private void init() {
paint.setColor(Color.BLACK);
}
public DrawView(Context context) {
super(context);
init();
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
#Override
public void onDraw(Canvas canvas) {
paint.setStrokeWidth(20);
canvas.drawLine(100, 100, 20, 20, paint);
canvas.drawLine(20, 0, 0, 20, paint);
}
}
I want the Canvas to be fairly large, so I need people to be able to scroll in both directions (left/right and up/down). How do I accomplish this? I'm unfamiliar with the Canvas class so any help will be appreciated.

If you want to draw on canvas with your custom height and width you have to call setContentView(android.view.View yourView , android.view.Viewgroup.LayoutParam yourLayout) in your activity class.Because by default setContentView(View view) method use full width and height.So you have to use its overloaded method with two parameter along with your desired. See documentation for more info.And don`t use only LayoutParams() constructor to create its object. Use it by writing its full path like android.view.ViewGroup.LayoutParams. Because there are some other classes with same name in Android SDK.
MyView customView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
customView = new MyView(getApplicationContext());
android.view.ViewGroup.LayoutParams lp = new android.view.ViewGroup.LayoutParams(100,200);//100 is width and 200 is height
setContentView(customView, lp);
customView.setOnClickListener(this);
}`

Related

canvas2Draw - how to connect view class to the canvas2

full code I'm new in android studio and I'm having problem with drawing.
Upon execution it does not work
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View eissa=new eissa(this);
setContentView(eissa);
}
}
class eissa extends View {
private Canvas canvas2;
private Bitmap backingbitmap;
public eissa(Context context) {
super(context);
backingbitmap=Bitmap.createBitmap(100,100,Bitmap.Config.ARGB_8888);
canvas2= new Canvas(backingbitmap);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(0,50,100,null);
canvas2.drawCircle(0,50,100,null);
canvas.drawBitmap(backingbitmap,0,0,null);
}
}
2.
There is a problem with the canvas.drawCircle() because there is no Paint argument (last one). The drawCircle doc says : "Paint: The paint used to draw the circle This value cannot be null."
So you can create a Paint in the constructor to pass to the drawCircle methods:
class eissa extends View {
private Canvas canvas2;
private Bitmap backingbitmap;
Paint viewPaint;
public eissa(Context context) {
super(context);
backingbitmap=Bitmap.createBitmap(100,100,Bitmap.Config.ARGB_8888);
canvas2= new Canvas(backingbitmap);
viewPaint = new Paint();
viewPaint.setColor(0xFFFF0000); // set your desired color here context.getColor(R.color....);
viewPaint.setStrokeWidth(4);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(0, 50, 100, viewPaint);
canvas2.drawCircle(0, 50, 100, viewPaint);
canvas.drawBitmap(backingbitmap, 0, 0, null);
}
}
1.
The view's dimensions are not specified anywhere causing the platform to use the default LayoutParams which have the layout_width and layout_height equal to WRAP_CONTENT so the view is not visible. To address ui issues you can use Tools / Layout inspector which can help identify the cause (incorrect dimensions).
Here is a good tutorial about measuring custom views.
The quickest fix would be to specify dimensions using LayoutParams in setContentView:
// replace setContentView() in onCreate() with this
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
setContentView(eissa, lp);

Blurred bitmap on canvas

I have View-based element in main activity and an image in drawable folder
public class MyView extends View {
private Bitmap mSprite;
public MyView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
mSprite = BitmapFactory.decodeResource(getResources(), R.drawable.plank);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mSprite, 0.f, 0.f, null);
}
}
The image is displayed but looks blurry and too large (ref). How can I get the actual size of bitmap and draw in on canvas?
For anyone faced the above issue: just put your image in nodpi folder and it will match its actual size.

How to solve draw() it does not draw my screen

I am trying to make a gaze tracking in android studio. And I am trying to draw on screen a rectangle to the corresponding point of gaze. But my method doesn't work. I don't have any experience in drawing in android studio.
This is my draw class
public class drawMargins extends View {
Paint paint;
private volatile Margin margin;
public drawMargins(Context context) {
super(context);
init(null);
}
public drawMargins(Context context, AttributeSet attrs)
{
super(context, attrs);
init(attrs);
}
public drawMargins(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public void updateMargin(Margin margin2) {
margin = margin2;
postInvalidate();
}
private void init(#Nullable AttributeSet set)
{
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
if (margin==null)
return;
paint = new Paint();
paint.setColor(Color.GREEN);
canvas.drawRect(
(float)((canvas.getWidth()/8)*margin.getX()),
(float)((canvas.getHeight()/8)*margin.getY()),
(float)((canvas.getWidth()/8)*margin.getX()+canvas.getWidth()/8),
(float)((canvas.getHeight()/8)*margin.getY()+canvas.getHeight()/8),paint);
}
}
and this is how I find the viewbyid("Draw") and update the vars:
DrawMargins = (drawMargins)LayoutInflater.from(context).inflate(R.layout.activity_live_preview,null).findViewById(R.id.Draw);
Margin eyeNose = new Margin(marginX(),marginY());
Margin drawOnScreen = onScreen(correspondingOnScreen(eyeNose,NEMargin,SEMargin,SWMargin,NWMargin,0),0,8,0,8,0 );
DrawMargins.updateMargin(drawOnScreen);
Should I call the draw method? With what canvas?
Try calling invalidate() instead of postInvalidate() in updateMargins(). This will call draw() and should draw the rectangle.
I would suggest you do one step at a time. I don't know exactly how you have your Activity or Fragment set, so I am just gonna go through that as well.
To keep things simple, let me assume that there is only Activity and no Fragments. You need two Java Class to get your objective accomplished: DrawMarginsActivity and DrawMargins.
DrawMargins is a Custom View. Custom views help you create your own custom drawing. Refer this for more details: https://developer.android.com/training/custom-views/custom-drawing . You need to override the onDraw(Canvas canvas) method. This method has the canvas parameter and you will be drawing on to this canvas.
Now you need to add DrawMargins view to your DrawMarginsActivity. You can do this by adding this view to your DrawMarginsActivity's layout file. Then you can get a reference to the DrawMargins view via findViewById().
Be default, when your Activity is created, the DrawMargins's onDraw() method will be called and it will render. But if you want to call the onDraw() again, you have to call DrawMargins.invalidate() method. This will invalidate the view and call the onDraw() method for you.
I am not sure on which action you want the view to draw. Based on that, you need to call the invalidate() method.

Null pointer exception when using multiple fragment that uses a custom seek bar

I have a custom Seek bar that that i made following a tutorial on the net. Here is the code for the CustomSeekBar class.
public class CustomSeekBar extends SeekBar {
private ArrayList<ProgressItem> mProgressItemsList;
public CustomSeekBar(Context context) {
super(context);
}
public CustomSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void initData(ArrayList<ProgressItem> progressItemsList) {
this.mProgressItemsList = progressItemsList;
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
protected void onDraw(Canvas canvas) {
if (mProgressItemsList.size() > 0) {
int progressBarWidth = getWidth();
int progressBarHeight = getHeight();
int thumboffset = getThumbOffset();
int lastProgressX = 0;
int progressItemWidth, progressItemRight;
for (int i = 0; i < mProgressItemsList.size(); i++) {
ProgressItem progressItem = mProgressItemsList.get(i);
Paint progressPaint = new Paint();
progressPaint.setColor(getResources().getColor(
progressItem.color));
progressItemWidth = (int) (progressItem.progressItemPercentage
* progressBarWidth / 100);
progressItemRight = lastProgressX + progressItemWidth;
// for last item give right to progress item to the width
if (i == mProgressItemsList.size() - 1
&& progressItemRight != progressBarWidth) {
progressItemRight = progressBarWidth;
}
Rect progressRect = new Rect();
progressRect.set(lastProgressX, thumboffset / 2,
progressItemRight, progressBarHeight - thumboffset / 2);
canvas.drawRect(progressRect, progressPaint);
lastProgressX = progressItemRight;
}
super.onDraw(canvas);
}
}
}
I have used this custom widget in a fragment. This fragment has multiple instance of this custom widget.
The fragment is used in multiple activities. There is an activity where the fragment works fine but in another activity where i try to use two of the above fragments i get a NullPointer Exception.
From the stacktrace i can trace the null pointer exception back to the line
if (mProgressItemsList.size() > 0) {
The strange thing is that when i add the fragment to only one framelayout the code works fine. But when i add the fragment to another framelayout in the same activity i get this null pointer exception. I am confused on what is causing this and am wondering what is the best way to tackle this?
The problem was that i was working with the view in the views of my fragment onActivityCreated() method. If you are planning to use the same fragment twice in any activity this is a very bad idea. I had two fragments initialized but only a single fragment and its views was initialized because i was using getActivity().findViewById() .
The solution to this is to work with your fragment's view on onViewCreated(View view, #Nullable Bundle savedInstanceState) and instead of using getActivity().findViewById() using view.findViewById().

Rotating a RelativeLayout in Android 2.3

I am new to android and would like some assistance on rotating my relative layout for a two-player game I am working on. I have seen the posts here and have looked into many other posts on the same subject on SO. My first question is how to I call the new class I just made? For all the posts that dont just tell me to use android:rotation (which is not avaliable in 2.3-) I make a new class, but I get a notification that the class is never called. Do I call the class simmilar to how I call a method? Or is there some command in AndroidManifest? Finialy, how does the new class rotate only one Relative layout and not the other? I just would like to know how its supposted to work.
This is the new Class that I am supposted to make:
public class MyRelativeLayout extends RelativeLayout {
public MyRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MyRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyRelativeLayout(Context context) {
super(context);
init();
}
private void init() {
setStaticTransformationsEnabled(true);
}
#Override
protected boolean getChildStaticTransformation(View child, Transformation t) {
t.setTransformationType(Transformation.TYPE_MATRIX);
Matrix m = t.getMatrix();
m.reset();
m.postRotate(180, child.getWidth() / 2.0f, child.getHeight() / 2.0f);
return true;
Thanks for your help
In the oncreate() method in your activity do setContentView(new MyRelativeLayout(this))

Categories

Resources