I've setup a fragment with a custom View for drawing strokes.
Right now I want to create a button for clearing the strokes, but this is not possible.
I have two classes
extending fragment class
extending the view class
To clear the canvas I've learned to do something like this:
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
The problem is that the Canvas object is stuck inside the onDraw() method.
But I need the canvas object in the button.setOnClickListener the clear the canvas.
How can I do this?
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import com.app.ssl.R;
import com.app.ssl.databinding.FragmentDrawviewBinding;
public class DrawviewFragment extends Fragment {
private FragmentDrawviewBinding binding;
private View root;
private View drawView;
private Button btnClear;
private Button btnSave;
public View onCreateView(
#NonNull LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceStage) {
root = inflater.inflate(R.layout.fragment_drawview,container,false);
drawView = root.findViewById(R.id.DrawingView);
btnClear = root.findViewById(R.id.btnClean1);
btnSave = root.findViewById(R.id.btnSave);
btnClear.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
System.out.println("CLEAR");
//drawView.setBackgroundColor(Color.WHITE);
// CLEAR CANVAS
//DrawView.canvas.drawColor(Color.WHITE);
//DrawView.canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
DrawView.canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.MULTIPLY);
//DrawView.onDraw(new Canvas());
}
});
btnSave.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
System.out.println("SAVE");
}
});
return root;
}
}
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class DrawView extends View {
private Paint drawPaint;
private Path path = new Path();
static Canvas canvas;
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusable(true);
setFocusableInTouchMode(true);
setupPaint();
}
// Setup paint with color and stroke styles
private void setupPaint() {
drawPaint = new Paint();
drawPaint.setColor(Color.BLACK);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(5);
drawPaint.setStyle(Paint.Style.STROKE); // draw with stroke
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
DrawView.canvas = canvas;
canvas.drawPath(path, drawPaint);
}
// Get x and y and append them to the path
public boolean onTouchEvent(MotionEvent event) {
float pointX = event.getX();
float pointY = event.getY();
// Checks for the event that occurs
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Starts a new line in the path
path.moveTo(pointX, pointY);
break;
case MotionEvent.ACTION_MOVE:
// Draws line between last point and this point
path.lineTo(pointX, pointY);
break;
default:
return false;
}
postInvalidate(); // Indicate view should be redrawn
return true; // Indicate we've co
}
}
I found the solution based on this Tutorial
Related
I am building an app that has multiple fragments and about half of those fragments contain a custom view that a user can draw lines with a finger (we'll call canvas), I am using a test app before I add new code to the main app. What I'm trying to do is to save the lines drawn by the user who then leaves the fragment for another one and draws some lines on the canvas in that fragment and can go back to the previous fragment (the drawing of the second will get saved) where the drawing for that fragment only will show in the canvas. If the user goes back to the second fragment, the drawing for the second fragment only will show, and also, the drawings should still be there when the app closes. I am using SharedPreferences.
When I go to one fragment (LineLHwFragment), I can draw on the canvas and click on save (I'll show where in the code) and it'll say "Data saved". If I close the app and load it again and go to that fragment, the drawing is not loaded.
Also, if I go to the other fragment (ChatFragment) either after clicking the first fragment or going to it first, the app crashes and I get this error message:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.Iterator java.util.ArrayList.iterator()' on a null object reference
at com.josullivan.mytestapplication.PaintView.onDraw(PaintView.java:112)
I am not sure as to why it is not loading the drawing or why it crashes
LineLHwFragment
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
public class LineLHwFragment extends Fragment {
private PaintView paintView;
public ArrayList test;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_line_l_hw, container, false);
paintView = v.findViewById(R.id.lineLPaintView);
//This should get the drawing to load
loadData();
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
paintView.init(metrics);
setHasOptionsMenu(true);
return v;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.normal:
paintView.normal();
//this is where the saving should happen when clicked
saveData();
return true;
case R.id.clear:
paintView.clear();
return true;
}
return super.onOptionsItemSelected(item);
}
private void saveData() {
SharedPreferences sharedPreferences = this.getActivity().getSharedPreferences("line test 1",
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
Gson gson = new Gson();
String json = gson.toJson(paintView.getPaths());
editor.putString("line test", json);
editor.apply();
Toast.makeText(this.getActivity(), "Data saved", Toast.LENGTH_SHORT).show();
}
private void loadData() {
SharedPreferences sharedPreferences = this.getActivity().getSharedPreferences("line test 1",
Context.MODE_PRIVATE);
Gson gson = new Gson();
String json = sharedPreferences.getString("line test", null);
Type type = new TypeToken<ArrayList<FingerPath>>() {}.getType();
test = paintView.getPaths();
test = gson.fromJson(json, type);
paintView.setPaths(test);
}
}
ChatFragment
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
public class ChatFragment extends Fragment {
private PaintView paintView;
public ArrayList test;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_chat, container, false);
paintView = v.findViewById(R.id.paintView1);
loadData();
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
paintView.init(metrics);
setHasOptionsMenu(true);
return v;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.normal:
paintView.normal();
saveData();
return true;
case R.id.clear:
paintView.clear();
return true;
}
return super.onOptionsItemSelected(item);
}
private void saveData() {
SharedPreferences sharedPreferences = this.getActivity().getSharedPreferences("chat test 1",
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
Gson gson = new Gson();
String json = gson.toJson(paintView.getPaths());
editor.putString("chat test", json);
editor.apply();
Toast.makeText(this.getActivity(), "Data saved", Toast.LENGTH_SHORT).show();
}
private void loadData() {
SharedPreferences sharedPreferences = this.getActivity().getSharedPreferences("chat test 1",
Context.MODE_PRIVATE);
Gson gson = new Gson();
String json = sharedPreferences.getString("chat test", null);
Type type = new TypeToken<ArrayList<FingerPath>>() {}.getType();
test = paintView.getPaths();
test = gson.fromJson(json, type);
paintView.setPaths(test);
}
}
PaintView.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.EmbossMaskFilter;
import android.graphics.MaskFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
public class PaintView extends View {
public static int BRUSH_SIZE = 10;
public static final int DEFAULT_COLOR = Color.WHITE;
public static int DEFAULT_BG_COLOR = Color.GRAY;
private static final float TOUCH_TOLERANCE = 4;
private float mX, mY;
private Path mPath;
private Paint mPaint;
private static ArrayList<FingerPath> paths = new ArrayList<>();
private int currentColor;
private int backgroundColor = DEFAULT_BG_COLOR;
private int strokeWidth;
private boolean emboss;
private boolean blur;
private MaskFilter mEmboss;
private MaskFilter mBlur;
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
public PaintView(Context context) {
this(context, null);
}
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(DEFAULT_COLOR);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setXfermode(null);
mPaint.setAlpha(0xff);
mEmboss = new EmbossMaskFilter(new float[] {1, 1, 1}, 0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(5, BlurMaskFilter.Blur.NORMAL);
}
public ArrayList getPaths() {
return paths;
}
public ArrayList setPaths(ArrayList<FingerPath> list) {
return this.paths = list;
}
//public Path getMPath() {
//return mPath;
// }
public void init(DisplayMetrics metrics) {
int height = metrics.heightPixels;
int width = metrics.widthPixels;
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
currentColor = DEFAULT_COLOR;
strokeWidth = BRUSH_SIZE;
}
public void normal() {
emboss = false;
blur = false;
}
public void clear() {
backgroundColor = DEFAULT_BG_COLOR;
paths.clear();
normal();
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
mCanvas.drawColor(backgroundColor);
//The null pointer exception points to this line
for (FingerPath fp: paths) {
mPaint.setColor(fp.color);
mPaint.setStrokeWidth(fp.strokeWidth);
mPaint.setMaskFilter(null);
if (fp.emboss)
mPaint.setMaskFilter(mEmboss);
else if (fp.blur)
mPaint.setMaskFilter(mBlur);
mCanvas.drawPath(fp.path, mPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.restore();
}
private void touchStart(float x, float y) {
mPath = new Path();
FingerPath fp = new FingerPath(currentColor, emboss, blur, strokeWidth, mPath);
paths.add(fp);
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touchMove(float x, float y) {
float dx = Math.abs(x-mX);
float dy = Math.abs(y-mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touchUp() {
mPath.lineTo(mX, mY);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN :
touchStart(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE :
touchMove(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP :
touchUp();
invalidate();
break;
}
return true;
}
}
I am trying to write a simple app that displays a coloured circle which fades to black as it gets further from the centre of the screen. However, whenever I click the app, it crashes. When I remove the onClick code the app runs fine. The only error I can find in logcat is:
Fatal signal 11 (SIGSEGV), code 1, fault addr 0x94 in tid 11955 (raphicstutorial)
And I don't know what to do with that.
Code below:
package com.example.a2dgraphicstutorial;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
public class MainActivity extends AppCompatActivity {
public class MyView extends View {
private Canvas thisCanvas;
private int colourID;
private Paint fillPaint = new Paint();
public MyView(Context context){
super(context);
colourID = 0;
fillPaint.setStyle(Paint.Style.FILL);
}
public void drawCircle(){
int x = getWidth();
int y = getHeight();
//Drawing the circles
for (int i = 255;i >= 0;i--){
//Determining colour
if (colourID == 0){
fillPaint.setColor(Color.argb(255,255-i,0,0));
}
else if (colourID == 1){
fillPaint.setColor(Color.argb(255,0,255-i,0));
}
else if (colourID == 2){
fillPaint.setColor(Color.argb(255,0,0,255-i));
}
thisCanvas.drawCircle(x/2,y/2,i,fillPaint);
}
//Cycling the colourID so the next circle will be a different colour
colourID = (colourID + 1)%3;
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
thisCanvas = canvas;
//Setting the background to be black
fillPaint.setColor(Color.parseColor("#000000"));
thisCanvas.drawPaint(fillPaint);
//Drawing the first circle
drawCircle();
}
}
MyView theScreen;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
theScreen = new MyView(this);
theScreen.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
theScreen.drawCircle();
}
});
setContentView(theScreen);
}
}
Instead of overriding the onCreate()
Override onTouchEvent() and listen to a click:
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//the finger is down do something.....
return true;
case MotionEvent.ACTION_UP:
//the finger is up do something.....(this is a click)
//to redraw
invalidate();
return true;
}
return false;
}
By the way:
To trigger the onDraw(), call this after a click:
invalidate();
One upon a time I had a problem similar to this
and the solutions was to replace "this" by "the name of activity".class
// replace this to theScreen = new MyView(this);
theScreen = new MyView(MainActivity.class);
Another solution is to replace this By "getBaseContext()"
// replace this to theScreen = new MyView(this);
theScreen = new MyView(getBaseContext());
this the context returns the current context of the activity, belong to the activity, the activity is destroyed then it will destroy also.
getBaseContext() is the method of ContextWrapper Which is "Proxying implementation of Context that simply delegates all of its calls to another Context. Can be subclassed to modify behaviour
without changing the original Context."
That error occurs when you call the Canvas outside of the onDraw method, try this code
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
public class MainActivity extends AppCompatActivity {
public class MyView extends View {
private Canvas thisCanvas;
private int colourID;
private Paint fillPaint = new Paint();
public MyView(Context context){
super(context);
colourID = 0;
fillPaint.setStyle(Paint.Style.FILL);
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
thisCanvas = canvas;
//Setting the background to be black
fillPaint.setColor(Color.parseColor("#000000"));
thisCanvas.drawPaint(fillPaint);
int x = getWidth();
int y = getHeight();
//Drawing the circles
for (int i = 255;i >= 0;i--){
//Determining colour
if (colourID == 0){
fillPaint.setColor(Color.argb(255,255-i,0,0));
}
else if (colourID == 1){
fillPaint.setColor(Color.argb(255,0,255-i,0));
}
else if (colourID == 2){
fillPaint.setColor(Color.argb(255,0,0,255-i));
}
thisCanvas.drawCircle(x/2,y/2,i,fillPaint);
}
//Cycling the colourID so the next circle will be a different colour
colourID = (colourID + 1)%3;
}
}
MyView theScreen;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
theScreen = new MyView(this);
theScreen.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
theScreen.invalidate();
}
});
setContentView(theScreen);
}
}
I moved the drawCircle method to inside the onDraw and change theScreen from calling drawCircle to call invalidate() instead, I'm not sure it's the result you want but at least that's the issue of the error.
I am brand new to android and i was wondering if it was possible to add toast onFinishInflate. If this is a stupid question please excuse me.I have created a view like this.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
import android.widget.Toast;
public class CustomView extends View {
private Rect rectangle;
private Paint paint;
public CustomView(Context context) {
super(context);
int x = 50;
int y = 50;
int sideLength = 200;
// create a rectangle that we'll draw later
rectangle = new Rect(x, y, sideLength, sideLength);
// create the Paint and set its color
paint = new Paint();
paint.setColor(Color.GRAY);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLUE);
canvas.drawRect(rectangle, paint);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
Toast.makeText(getApplicationContext(),"onfinishinflate",Toast.LENGTH_SHORT).show();
}
}
Update
View has it's own method called getContext(), so you can use like this
Toast.makeText(getContext(), "onfinishinflate", Toast.LENGTH_SHORT).show();
Reference
private Context context;
public CustomView(Context context) {
super(context);
this.context = context;
// Rest of ur codes
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
Toast.makeText(context, "onfinishinflate", Toast.LENGTH_SHORT).show();
}
set the context in your class using constructor, and use it for Toast purpose
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
Recently I fixed an error, but now I'm stuck at clearing the canvas for my draw project. I already took a look at some other topics with the same question, but it didn't fix my problem.
package org.arkmap.klaas.testdrawing;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
public class WriteOnScreenActivity extends AppCompatActivity {
Button clear;
TouchEventView myView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_on_screen);
clear=(Button)findViewById(R.id.clearbutton);
myView = new TouchEventView(this, null);
clear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View vw) {
myView.clearCanvas();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_write_on_screen, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
WriteOnScreenActivity.java
package org.arkmap.klaas.testdrawing;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.Random;
/**
* Created by Startklaar on 19-1-2016.
*/
public class TouchEventView extends View {
public Paint paint = new Paint();
private Path path = new Path();
public boolean cc = false;
Random rnd = new Random();
public TouchEventView(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
paint.setAntiAlias(true);
paint.setARGB(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
//paint.setColor(Color.WHITE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10f);
}
#Override
protected void onDraw(Canvas canvas) {
if (cc) {
path = new Path();
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, 0, 0, clearPaint);
cc = false;
}
canvas.drawPath(path, paint);
}
public void clearCanvas()
{
cc = true;
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float xPos = event.getX();
float yPos = event.getY();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(xPos, yPos);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(xPos,yPos);
break;
case MotionEvent.ACTION_UP:
break;
default:
return false;
}
invalidate();
return true;
}
}
TouchEventView.java
Hope to get some help here!
EDIT: The error has been fixed, the only problem I have is that the button is not functioning.
myView is not being initialized. You should set it:
myView = (TouchEventView) findViewById(R.id.XXXX);
When I start dragging the image its automatically goes to the right corner and just than it start to move.
here is example:
--its start from the center--
![when I touch the image]http://i59.tinypic.com/2dbjp7d.png
![when i move the image]http://i60.tinypic.com/33l1f6c.png
package com.example.smite.floater;
import android.app.Service;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.os.IBinder;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.Toast;
public class floatingwindow extends Service{
private WindowManager wm;
private LinearLayout ll;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
wm = (WindowManager)getSystemService(WINDOW_SERVICE);
ll = new LinearLayout(this);
LinearLayout.LayoutParams llParameters = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
ll.setBackgroundResource(R.mipmap.floatbutton2);
ll.setLayoutParams(llParameters);
final WindowManager.LayoutParams parameters = new WindowManager.LayoutParams(75,75,WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
parameters.x=0;
parameters.y=0;
parameters.gravity= Gravity.CENTER | Gravity.CENTER;
wm.addView(ll , parameters);
ll.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "clicked", Toast.LENGTH_LONG).show();
}
});
ll.setOnTouchListener(new View.OnTouchListener() {
private WindowManager.LayoutParams updatedParameters = parameters;
int x , y;
float touchedX , touchedY;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
x = updatedParameters.x;
y = updatedParameters.y;
touchedX = event.getX();
touchedY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
updatedParameters.x = (int)(x + (event.getRawX() - touchedX));
updatedParameters.y = (int)(y + (event.getRawY() - touchedY));
wm.updateViewLayout(ll, updatedParameters);
default:
break;
}
return false;
}
});
}
}
what to do??
why its start from the corner and not from the last position?
thanks