I'm new to Android. Here I draw a rectangle.
public class DrawView extends View
{
Paint paint = new Paint();
public DrawView(Context context)
{
super(context);
}
#Override
public void onDraw(Canvas canvas)
{
paint.setColor(Color.BLACK);
canvas.drawRect(30f, 30f, 80f, 80f, paint);
}
}
My XML code for adding button is :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:id="#+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="90dp"
android:layout_toRightOf="#+id/textView1"
android:text="Button" />
</RelativeLayout>
I have 2 doubts.
1)I want the rectangle in top of the app and the button in the bottom. How should I do it?
2) Later I want to change the color of rectangle. How should I get the rectangle to change the attributes?
1) Add the rectangle to your layout xml.-
<packageRouteToYourExtendedView.DrawView
android:id="#+id/rectangle"
android:layout_width="30dp"
android:layout_height="80dp"
android:layout_alignParentTop="true" />
2) Add a method to your extended view to change the color.-
public class DrawView extends View
{
Color color = Color.BLACK;
Paint paint = new Paint();
public DrawView(Context context)
{
super(context);
}
#Override
public void onDraw(Canvas canvas)
{
paint.setColor(color);
canvas.drawRect(30f, 30f, 80f, 80f, paint);
}
public changeColor(Color color) {
this.color = color;
invalidate();
}
}
And get the rectangle view to call your new method.-
DrawView rectangle = findViewById(R.id.rectangle);
rectangle.changeColor(Color.BLUE);
Related
I have a strange problem I'm creating a canvas drawing app in Android that has lots of buttons in xml file. The problems is when I draw a circle with all those buttons included in the file it's never a smooth circle it's full of corners like hexagon shape but when I exclude buttons may be leaving in one or two, it draws a perfect smooth circle. I have tried to split the file into three so I've included them using but still same result. Can someone please enlighten me what am I do wrong.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!--First Draw -->
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageButton
android:id="#+id/nav_one"
android:layout_width="30dp"
android:layout_height="60dp"
android:layout_marginTop="100dp"
android:layout_marginBottom="100dp"
android:background="#drawable/ic_tab_res_bkg"/>
<ImageButton
android:id="#+id/nav_two"
android:layout_width="30dp"
android:layout_height="60dp"
android:layout_marginTop="200dp"
android:background="#drawable/ic_tab_tools_bkg"/>
</LinearLayout>
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="#+id/resource_bank"
android:layout_width="350dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/background_light"
android:dividerHeight="0dp"
android:background="#f4f1f1"
/>
<ListView android:id="#+id/tools"
android:layout_width="350dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:choiceMode="singleChoice"
android:divider="#android:color/background_light"
android:dividerHeight="0dp"
android:background="#dedada"/>
</android.support.v4.widget.DrawerLayout>
<RelativeLayout
android:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" >
<xxxxx.xxxxxx.xxxx.xxxxxx.DrawView
android:id="#+id/canvas_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/canvas_view">
<!-- Pen icons -->
<include layout="#layout/activity_pen_color" android:id="#+id/pen_color" />
<include layout="#layout/activity_pen_style" android:id="#+id/pen_style" />
<!-- Navigation bar icons -->
<ImageView
android:id="#+id/icon_bar"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_gravity="bottom"
android:background="#drawable/icon_bar_bkg"
/>
<Button
android:id="#+id/ic_select"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="150dp"
android:layout_marginTop="60dp"
android:elevation="1dp"
android:background="#drawable/ic_select_bkg"/>
<TextView
android:id="#+id/text_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="150dp"
android:layout_marginTop="90dp"
android:text="Select"
android:textColor="#color/colorAccent"
/>
<Button
android:id="#+id/ic_pens"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="200dp"
android:layout_marginTop="60dp"
android:elevation="1dp"
android:background="#drawable/ic_pen_bkg"/>
<TextView
android:id="#+id/text_pens"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="200dp"
android:layout_marginTop="90dp"
android:text="Pen"
android:textColor="#color/colorAccent"
/>
</FrameLayout>
</RelativeLayout>
My DrawView
public class DrawView extends View {
private Paint drawPaint, canvasPaint;
private Canvas drawCanvas;
private Bitmap canvasBitmap;
private SparseArray<Path> paths;
public DrawView(Context context) {
super(context);
setupDrawing();
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
}
public DrawView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setupDrawing();
}
private void setupDrawing() {
paths = new SparseArray<>();
drawPaint = new Paint();
drawPaint.setColor(Color.BLACK);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(9);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
for (int i=0; i<paths.size(); i++) {
canvas.drawPath(paths.valueAt(i), drawPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int index = event.getActionIndex();
int id = event.getPointerId(index);
Path path;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
path = new Path();
path.moveTo(event.getX(index), event.getY(index));
paths.put(id, path);
break;
case MotionEvent.ACTION_MOVE:
for (int i=0; i<event.getPointerCount(); i++) {
id = event.getPointerId(i);
path = paths.get(id);
if (path != null) path.lineTo(event.getX(i), event.getY(i));
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
path = paths.get(id);
if (path != null) {
drawCanvas.drawPath(path, drawPaint);
paths.remove(id);
}
break;
default:
return false;
}
invalidate();
return true;
}
/**
* change path color here
*/
public void setPathColor(int color) {
drawPaint.setColor(color);
}
}
Answer
I take it that you are drawing this circle with your finger, and that when a lot of extra buttons are present, you notice that the lines you draw with your finger become "less smooth".
This is related to the app's screen refresh rate. When your app has to spend lots of time drawing all those extra buttons, it has fewer opportunities to get MotionEvents. With fewer MotionEvents, there are fewer points in your shape, and it takes longer line segments to connect them.
Suggested fix
The recommended approach is to stop those button views from being invalidated (an assumption on my part) every time onTouchEvent() gets called. From your code, I can't immediately see why they would be invalidated, but it may be that your DrawView underlies the buttons you are adding, thus whenever the DrawView is invalidate()-ed, the system must re-compose it with the buttons. You could move the DrawView so that it's by itself. Adding an opaque background to your button container(s) may help as well, b/c the system would have to do fewer alpha calculations.
You must have a lot of buttons... you may want to do some performance profiling to determine exactly what's taking so long.
So, I need to overlay the camera2 preview and draw a rectangle on the preview video image by layering a transparent overlay on top. I started with a basic Camera2 code here: https://github.com/googlesamples/android-Camera2Basic
the above use TextureView for camera preview.
Next, I added the following class to project
private class CustomView extends SurfaceView {
private final Paint paint;
private final SurfaceHolder mHolder;
private final Context context;
public CustomView(Camera2BasicFragment context) {
super(context.getActivity().getBaseContext());
mHolder = getHolder();
mHolder.setFormat(PixelFormat.TRANSPARENT);
this.context = context.getActivity().getBaseContext();
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
invalidate();
if (mHolder.getSurface().isValid()) {
final Canvas canvas = mHolder.lockCanvas();
Log.d("touch", "touchRecieved by camera");
if (canvas != null) {
Log.d("touch", "touchRecieved CANVAS STILL Not Null");
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawColor(Color.TRANSPARENT);
canvas.drawCircle(event.getX(), event.getY(), 100, paint);
mHolder.unlockCanvasAndPost(canvas);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Canvas canvas1 = mHolder.lockCanvas();
if(canvas1 !=null){
canvas1.drawColor(0, PorterDuff.Mode.CLEAR);
mHolder.unlockCanvasAndPost(canvas1);
}
}
}, 1000);
}
mHolder.unlockCanvasAndPost(canvas);
}
}
return false;
}
}
I need some help in making this work.. Obviously the new class is not used yet. I also need to update the overlay xml to add a second transparent TextureView on top of the camera preview one. Here is my original layout:
Would be very appreciated if anyone can tell me how to make the new class work, and tell me what to add to the layout.
here is fragment_camera2_basic.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.android.camera2basic.AutoFitTextureView
android:id="#+id/texture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
<FrameLayout
android:id="#+id/control"
android:layout_width="match_parent"
android:layout_height="112dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:background="#color/control_background">
<Button
android:id="#+id/picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="#string/picture" />
<ImageButton
android:id="#+id/info"
android:contentDescription="#string/description_info"
style="#android:style/Widget.Material.Light.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|right"
android:padding="20dp"
android:src="#drawable/ic_action_info" />
</FrameLayout>
</RelativeLayout>
and activity_camera.xml
<?xml version="1.0" encoding="utf-8"?><!--
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000"
tools:context="com.example.android.camera2basic.CameraActivity" />
Add
<LinearLayout
android:id="#+id/surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
Within the fragment. I've added a RelativeLayout around AutoFitTextureView and FrameLayout, but not sure if that is needed.
Change onCreateView to
View view = inflater.inflate(R.layout.fragment_camera2_basic, container, false);
LinearLayout surface = (LinearLayout)view.findViewById(R.id.surface);
surface.addView(new CustomView(this));
return view;
I'm trying to use SurfaceView and want to paint on it, use code:
public class TestPaint extends SurfaceView {
public TestPaint(Context context) {
super(context);
setWillNotDraw(false);
setBackgroundColor(color.white);
}
#Override
protected void onDraw(Canvas canvas) {
Paint p = new Paint();
p.setColor(color.black);
canvas.drawText("test", 10, 10, p);
}
}
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TestPaint p=new TestPaint(this);
p.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
LinearLayout rl=(LinearLayout) findViewById(R.id.rltMain);
rl.addView(p);
}
}
The TestPaint display black background only. I try Why do I get it?
Using paint class better then that you have use frame layout and set text view or whatever u want.
Check this,
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<SurfaceView
android:id="#+id/surfaceView1"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</SurfaceView>
</LinearLayout>
<TextView
android:id="#+id/test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|right"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:text="test"
android:background="#color/abc_search_url_text_normal"
android:textColor="#android:color/black"
android:textSize="20sp" />
</FrameLayout>
I have a custom view where there is a Canvas drawn with circles and lines. My problem is that once transferred to the tablet look cropped image and not real. Is there a way to resize the CustomView and fit the screen automatically, or even scroll the image.
A bit of code:
public class CustomView extends View {
Paint pPaint;
Paint cPaint;
Paint textPaint;
int w,h;
int px=150,py=150;
int cx=450,cy=150;
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
pPaint=new Paint(); // pennello
pPaint.setColor(Color.RED);
pPaint.setAntiAlias(true);
cPaint=new Paint(); // pennello
cPaint.setColor(Color.CYAN);
cPaint.setAntiAlias(true);
textPaint=new Paint(); // pennello
textPaint.setColor(Color.BLACK);
textPaint.setAntiAlias(true);
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<com.abstractargument.CustomView
android:id="#+id/customView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
</RelativeLayout>
I just created a view for displaying PDF file
public class PDFGraphic extends View{
String mText;
float mLastX;
float mLastY;
public float mOffX;
public float mOffY;
Canvas mCan;
Bitmap mBi;
public PDFGraphic(Context context, AttributeSet attrs){
super(context,attrs);
setPageBitmap();
setBackgroundColor(Color.TRANSPARENT);
}
public void uiInvalidate() {
postInvalidate();
}
public void setPageBitmap() {
mBi = Bitmap.createBitmap(100, 100, Config.RGB_565);
mCan = new Canvas(mBi);
mCan.drawColor(Color.RED);
}
public void onDraw(Canvas canvas) {
Paint paint = new Paint();
canvas.drawBitmap(mBi, 0, 0, paint);
}
}
And this is my xml file(pdfview):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" android:orientation="vertical">
<RelativeLayout android:id="#+id/relativeLayout1" android:layout_width="match_parent" android:gravity="bottom|center" android:layout_height="wrap_content" android:minHeight="30px" android:visibility="visible">
<com.shawnprojectPDF.PDFGraphic android:id="#+id/pdfview1" android:layout_width="match_parent" android:layout_above="#+id/editText1" android:layout_alignParentTop="true" android:layout_height="match_parent"></com.shawnprojectPDF.PDFGraphic>
<ImageButton android:layout_height="wrap_content" android:layout_width="wrap_content" android:src="#drawable/leftarray" android:id="#+id/left" android:layout_alignParentBottom="true" android:layout_marginLeft="68px"></ImageButton>
<EditText android:id="#+id/editText1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="#+id/left" android:layout_alignParentBottom="true" android:gravity="center" android:width="100px" android:singleLine="true" android:maxLength="12"></EditText>
<ImageButton android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="#+id/right" android:src="#drawable/rightarray" android:layout_toRightOf="#+id/editText1" android:layout_alignParentBottom="true"></ImageButton>
</RelativeLayout>
</LinearLayout>
In my main activity,if setContentView(R.Layout.pdfview), the view(PDFGraphic) will not be invalidated, if setContentView(New PDFGraphic(this)),it invalidates successfully.
How to refresh the view in the whole layout.
I don't see the problem. These are the results that I get with your code (next time, you do this part). With setContentView(R.layout.pdfview), this is the result:
With setContentView(new PDFGraphic(this, null) -- note that I used the two-arg constructor because you didn't define PDFGraphic(Context) -- this is the result:
In either case, your onDraw() is happening correctly.