I implemented a canvas for drawing on Android, but the drawing view fills the screen. I want to adjust the size of this screen. What should I do?
Once I set MyView to show with setContentView in oncreate method.
MainActivity.java
MyView view = new MyView(this);
setContentView(view);
And here is the part of painting on the canvas. However, as mentioned earlier, I want to adjust the range in which I can draw. I don't want the whole screen to be a drawing view.
MyView.java
public class MyView extends View {
private Paint paint = new Paint();
private Path path = new Path();
private int x,y;
public MyView(Context context){
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
paint.setColor(Color.BLACK);
//STROKE속성을 이용하여 테두리...선...
paint.setStyle(Paint.Style.STROKE);
//두께
paint.setStrokeWidth(3);
//path객체가 가지고 있는 경로를 화면에 그린다...
canvas.drawPath(path,paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
x = (int)event.getX();
y = (int)event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
path.moveTo(x,y);
break;
case MotionEvent.ACTION_MOVE:
x = (int)event.getX();
y = (int)event.getY();
Log.e("s",x+""+y);
path.lineTo(x,y);
break;
}
//View의 onDraw()를 호출하는 메소드...
invalidate();
return true;
}
}
You can set width and height like this:
MyView view = new MyView(this);
setContentView(view);
view.setLayoutParams(new FrameLayout.LayoutParams(500, 500));
Where the FrameLayout.LayoutParams can vary for the parent ViewGroup. If the parent is LinearLayout, it should be LinearLayout.LayoutParams, and so on.
Related
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);
I know how it can be applied to the toolbar w.r.t. any scrollView in Coordinator layout.
I wanna do the same thing with the button w.r.t. RecycleView.
Just like the bottomNav in the app Pinterest.
Thanks!
A simple way that comes to mind is to use the TranslateAnimation provided by Android and to check if the RecyclerView is being scrolled. Here is what you need to do
Add a scroll listener to the RecyclerView and check if the scrolling direction is downward or upward
YourRecyclerView.addScrollListener(new ScrollListener() {
someScrollListenerMethod() {
if (scrolling up) {
showButton();
} else {
hideButton();
}
}
);
Create an animation for sliding the button up and down.
slideDownAnimation = TranslateAnimation(0f, 0f, 0f, ScreenHeight)
slideDownAnimation.duration = 1000f //1 second
slideUpAnimation = TranslateAnimation(0f, 0f, ScreenHeight, 0f)
slideUpAnimation.duration = 1000f //1 second
Create the show and hide button methods which will show and hide the button
private void showButton() {
yourButton.visibility = View.VISIBLE;
yourButton.startAnimation(slideUpAnimation);
}
private void hideButton() {
yourButton.visibility = View.INVISIBLE;
yourButton.startAnimation(slideDownAnimation);
}
Just a note, the code shared in step 1 is not the actual library code (I could not remember the exact code) but you can easily find it out.
Here's the applied code as explained by Bilal. Just in case anybody need it,
private void buttonSlideAnimation() {
addButton = findViewById(R.id.bottom_add_button);
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
final TranslateAnimation slideDownAnimation = new TranslateAnimation(0f, 0f, 0f, height);
final TranslateAnimation slideUpAnimation = new TranslateAnimation(0f, 0f, height, 0f);
slideDownAnimation.setDuration(1000);
slideUpAnimation.setDuration(1000);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy>0){
addButton.setVisibility(View.INVISIBLE);
addButton.startAnimation(slideDownAnimation);
} else {
addButton.setVisibility(View.VISIBLE);
addButton.startAnimation(slideUpAnimation);
}
}
});
}
I'm trying to draw over an image, which i'll save later with the drawings. My xml only have the ImageView and I tried to overwrite onDraw. It only made de Canvas works, but with no image.
public class Body1 extends View {
public LayoutParams params;
private Path path = new Path();
private Paint brush = new Paint();
public Body1(Context context) {
super(context);
brush.setAntiAlias(true);
brush.setColor(Color.MAGENTA);
brush.setStyle(Paint.Style.STROKE);
brush.setStrokeJoin(Paint.Join.ROUND);
brush.setStrokeWidth(8f);
params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float pointX = event.getX();
float pointY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(pointX, pointY);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(pointX, pointY);
break;
default:
return false;
}
postInvalidate();
return false;
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, brush);
}
}
OK you are on the right path.
What you are missing is invalidate calls that will result in the OS calling the OnDraw of the view.
Call invalidate every time you want to update the view. But notice that your class has only a single path object and so will only draw the last segment.
If I'm not mistaken you should hold an ArrayList of Path objects.
In onDraw you should loop over them and draw them all one after the other.
I know this question has been asked many times on SO. I have read most of them, but they don't work for me, so don't bother marking duplicates.
Here is my code, and what I have tried so far:
RelativeLayout container = new RelativeLayout(this.getContext());
TextView tv = new TextView(this.getContext());
tv.setText(txt); // a single digit like '3'
tv.setLines(1);
tv.layout(0, offsety, cellszie, offsety+cellsize);
tv.setTextAlignment(TextView.TEXT_ALIGNMENT_CENTER);
tv.setGravity(Gravity.CENTER);
// I also tried CENTER_VERTIAL and the following line
// tv.setGravity(CENTER_VERTIAL| CENTER_HORIZONTAL);
// I also tried giving LayoutParams to tv like this:
// tv.setLayoutParams(new LayoutParams(cellsize, cellsize));
// tv.setLayoutParams(new LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
// tv.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
container.addView(tv);
The character is horizontally centered, but it floats on the top of the TextView vertically. Setting gravity and LayoutParams doesn't change its behavior.
What should I do to make it center vertically?
use this class for VerticalTextView.
public class VerticalTextView extends TextView {
final boolean topDown;
public VerticalTextView(Context context, AttributeSet attrs){
super(context, attrs);
final int gravity = getGravity();
if(Gravity.isVertical(gravity) && (gravity&Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
setGravity((gravity&Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
topDown = false;
}else
topDown = true;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
#Override
protected void onDraw(Canvas canvas){
TextPaint textPaint = getPaint();
textPaint.setColor(getCurrentTextColor());
textPaint.drawableState = getDrawableState();
canvas.save();
if(topDown){
canvas.translate(getWidth(), 0);
canvas.rotate(90);
}else {
canvas.translate(0, getHeight());
canvas.rotate(-90);
}
canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
getLayout().draw(canvas);
canvas.restore();
}
}
you can do it like this
RelativeLayout container = new RelativeLayout(this.getContext());
View view = layoutInflater.inflate(R.layout.my_layout_file, null);
container.addView(view);
where R.layout.my_layout_file contains textview with gravity center. and here you can get object of textview like this
textviewObject = (TextView)view.findViewById(R.id.textViewId)
Try setting RelativeLayout.LayoutParams to you RelativeLayout
RelativeLayout.LayoutParams relativeLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
container.setLayoutParams(relativeLayoutParams)
Then set the gravity for your TextView:
tv.setGravity(Gravity.CENTER);
Then add the view to your RelativeLayout:
container.addView(tv);
First of all, thanks in advance for any help you can provide. This has been driving me nuts and google's been no friend of mine for this.
I've created a DrawView so the user can paint something in the app. What I'd like to do is place that DrawView within a layout XML file, so I can place a TextView title on the top and two buttons on the bottom, one of which will save what the user painted as an image file. So far, all I've been able to do is create an area for the user to paint in. Is there any way to place this DrawView view into an XML file? If not, what alternative solutions do I have?
Also, this is an optional question as I'm sure I'll find the solution by googling, at some point, but is there a better way to smoothly draw along the user's finger movement, other than the canvas.drawLine() method I am currently using?
public class Draw extends Activity {
DrawView drawView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set full screen view
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
drawView = new DrawView(this);
setContentView(drawView);
drawView.requestFocus();
}
}
public class DrawView extends View implements OnTouchListener {
private static final String TAG = "DrawView";
ArrayList <Float> nikpointx = new ArrayList<Float>();
ArrayList <Float> nikpointy = new ArrayList<Float>();
Bitmap nikbmp;
Paint paint = new Paint();
public DrawView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
paint.setColor(Color.WHITE);
paint.setAntiAlias(true);
paint.setStrokeWidth(4);
}
#Override
public void onDraw(Canvas canvas) {
//I'm doing this, because the drawCircle method places circles at different points
//in the screen, rather than drawing smooth lines. I haven't found a more elegant
//solution yet :-(
canvas.drawLine(nikpointx.get(i-1), nikpointy.get(i-1), nikpointx.get(i), nikpointy.get(i), paint);
canvas.setBitmap(nikbmp);
}
}
public boolean onTouch(View view, MotionEvent event) {
// if(event.getAction() != MotionEvent.ACTION_DOWN)
// return super.onTouchEvent(event);
Point point = new Point();
point.x = event.getX();
point.y = event.getY();
points.add(point);
invalidate();
Log.d(TAG, "point: " + point);
nikpointx.add(event.getX());
nikpointy.add(event.getY());
return true;
}
}
You can place you custom view in the xml layout like this:
<full.package.to.customview.DrawView android:id="#+id/idOfCustom"
//other attributes
/>
You can also add custom attributes to your view to set directly from the xml file.
I don't have any solutions for your second problem.
edit: after a quick search on this site i found this -> Android How to draw a smooth line following your finger