Custom Drawing View load drawable image inside it - android

I've searched, but haven't found anything I'm looking for, perhaps. I want load image into my custom drawing view. Here is the code of DrawingView that extend View.
private Path mDrawPath;
private Paint mBackgroundPaint;
private Paint mDrawPaint;
private Canvas mDrawCanvas;
private Bitmap mCanvasBitmap;
private ArrayList<Path> mPaths = new ArrayList<>();
private ArrayList<Paint> mPaints = new ArrayList<>();
private ArrayList<Path> mUndonePaths = new ArrayList<>();
private ArrayList<Paint> mUndonePaints = new ArrayList<>();
// Set default values
private int mBackgroundColor = 0xFFFFFFFF;
private int mPaintColor = 0xFF660000;
private int mStrokeWidth = 10;
public DrawingView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
private void init()
{
mDrawPath = new Path();
mBackgroundPaint = new Paint();
initPaint();
}
private void initPaint()
{
mDrawPaint = new Paint();
mDrawPaint.setColor(mPaintColor);
mDrawPaint.setAntiAlias(true);
mDrawPaint.setStrokeWidth(mStrokeWidth);
mDrawPaint.setStyle(Paint.Style.STROKE);
mDrawPaint.setStrokeJoin(Paint.Join.ROUND);
mDrawPaint.setStrokeCap(Paint.Cap.ROUND);
}
private void drawBackground(Canvas canvas)
{
mBackgroundPaint.setColor(Color.TRANSPARENT);
mBackgroundPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
mBackgroundPaint.setAntiAlias(true);
canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), mBackgroundPaint);
}
private void drawPaths(Canvas canvas)
{
int i = 0;
for (Path p : mPaths)
{
canvas.drawPath(p, mPaints.get(i));
i++;
}
}
#Override
protected void onDraw(Canvas canvas)
{
drawBackground(canvas);
drawPaths(canvas);
canvas.drawPath(mDrawPath, mDrawPaint);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mCanvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mDrawCanvas = new Canvas(mCanvasBitmap);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
mDrawPath.moveTo(touchX, touchY);
//mDrawPath.addCircle(touchX, touchY, mStrokeWidth/10, Path.Direction.CW);
break;
case MotionEvent.ACTION_MOVE:
mDrawPath.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
mDrawPath.lineTo(touchX, touchY);
mPaths.add(mDrawPath);
mPaints.add(mDrawPaint);
mDrawPath = new Path();
initPaint();
break;
default:
return false;
}
invalidate();
return true;
}
public void clearCanvas()
{
mPaths.clear();
mPaints.clear();
mUndonePaths.clear();
mUndonePaints.clear();
mDrawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
}
public void setPaintColor(int color)
{
mPaintColor = color;
mDrawPaint.setColor(mPaintColor);
}
public void setPaintStrokeWidth(int strokeWidth)
{
mStrokeWidth = strokeWidth;
mDrawPaint.setStrokeWidth(mStrokeWidth);
}
public void setBackgroundColor(int color)
{
mBackgroundColor = color;
mBackgroundPaint.setColor(mBackgroundColor);
invalidate();
}
public Bitmap getBitmap()
{
drawBackground(mDrawCanvas);
drawPaths(mDrawCanvas);
return mCanvasBitmap;
}
public void undo()
{
if (mPaths.size() > 0)
{
mUndonePaths.add(mPaths.remove(mPaths.size() - 1));
mUndonePaints.add(mPaints.remove(mPaints.size() - 1));
invalidate();
}
}
public void redo()
{
if (mUndonePaths.size() > 0)
{
mPaths.add(mUndonePaths.remove(mUndonePaths.size() - 1));
mPaints.add(mUndonePaints.remove(mUndonePaints.size() - 1));
invalidate();
}
}
BoardActivity class code is:
private TextView titolo;
private DrawingView areaDisegno;
private ImageView sceltaColore, sceltaSpessore, undo, redo;
private Bitmap drawable;
private int mCurrentBackgroundColor;
private int mCurrentColor;
private int mCurrentStroke;
private static final int MAX_STROKE_WIDTH = 50;
#Override
protected void onCreate(Bundle savedInstanceState) {
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setNavigationBarColor(getResources().getColor(R.color.black));
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_board1);
titolo = findViewById(R.id.titolo);
titolo.setText("MATCHUP BOARD 1");
areaDisegno = findViewById(R.id.area_disegno);
sceltaColore= findViewById(R.id.scelta_colore);
sceltaSpessore = findViewById(R.id.scelta_spessore);
undo = findViewById(R.id.undo);
redo = findViewById(R.id.redo);
sceltaColore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startColorPickerDialog();
}
});
sceltaSpessore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startStrokeSelectorDialog();
}
});
undo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
areaDisegno.undo();
}
});
redo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
areaDisegno.redo();;
}
});
inizializzaAreaDisegno();
}
private void inizializzaAreaDisegno()
{
// mCurrentBackgroundColor = ContextCompat.getColor(this, android.R.color.white);
mCurrentColor = ContextCompat.getColor(this, android.R.color.black);
mCurrentStroke = 10;
areaDisegno.setBackgroundColor(mCurrentBackgroundColor);
areaDisegno.setPaintColor(mCurrentColor);
areaDisegno.setPaintStrokeWidth(mCurrentStroke);
}
private void startFillBackgroundDialog()
{
int[] colors = getResources().getIntArray(R.array.palette);
ColorPickerDialog dialog = ColorPickerDialog.newInstance(R.string.color_picker_default_title,
colors,
mCurrentBackgroundColor,
5,
ColorPickerDialog.SIZE_SMALL);
dialog.setOnColorSelectedListener(new ColorPickerSwatch.OnColorSelectedListener()
{
#Override
public void onColorSelected(int color)
{
mCurrentBackgroundColor = color;
areaDisegno.setBackgroundColor(mCurrentBackgroundColor);
}
});
dialog.show(getFragmentManager(), "ColorPickerDialog");
}
private void startColorPickerDialog()
{
int[] colors = getResources().getIntArray(R.array.palette);
ColorPickerDialog dialog = ColorPickerDialog.newInstance(R.string.color_picker_default_title,
colors,
mCurrentColor,
5,
ColorPickerDialog.SIZE_SMALL);
dialog.setOnColorSelectedListener(new ColorPickerSwatch.OnColorSelectedListener()
{
#Override
public void onColorSelected(int color)
{
mCurrentColor = color;
areaDisegno.setPaintColor(mCurrentColor);
}
});
dialog.show(getFragmentManager(), "ColorPickerDialog");
}
private void startStrokeSelectorDialog()
{
StrokeSelectorDialog dialog = StrokeSelectorDialog.newInstance(mCurrentStroke, MAX_STROKE_WIDTH);
dialog.setOnStrokeSelectedListener(new StrokeSelectorDialog.OnStrokeSelectedListener()
{
#Override
public void onStrokeSelected(int stroke)
{
mCurrentStroke = stroke;
areaDisegno.setPaintStrokeWidth(mCurrentStroke);
}
});
dialog.show(getSupportFragmentManager(), "StrokeSelectorDialog");
}
private void startShareDialog(Uri uri)
{
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("image/*");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "");
intent.putExtra(android.content.Intent.EXTRA_TEXT, "");
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(intent, "Share Image"));
}
private void requestPermissionsAndSaveBitmap()
{
if (PermissionManager.checkWriteStoragePermissions(this))
{
Uri uri = FileManager.saveBitmap(this, areaDisegno.getBitmap());
startShareDialog(uri);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
{
case PermissionManager.REQUEST_WRITE_STORAGE:
{
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Uri uri = FileManager.saveBitmap(this, areaDisegno.getBitmap());
startShareDialog(uri);
} else
{
Toast.makeText(this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
}
}
And Layout used is:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
android:background="#drawable/sfondo"
tools:context=".activities.Board1">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusableInTouchMode="true">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar_menu_disegno"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar"
android:orientation="vertical"
android:weightSum="2"
>
<FrameLayout
android:layout_weight="1.99"
android:layout_width="match_parent"
android:layout_height="0dp" >
<it.colan.matchup.ui.component.DrawingView
android:id="#+id/area_disegno"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:rotation="90"
android:src="#drawable/board_1" />
</FrameLayout>
<LinearLayout
android:id="#+id/menu_strumenti"
android:layout_weight="0.01"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/area_disegno"
android:orientation="horizontal"
android:gravity="center"
android:background="#color/black">
<ImageView
android:id="#+id/scelta_colore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_palette"
android:padding="15dp"
android:clickable="true"
android:background="?attr/selectableItemBackgroundBorderless"/>
<ImageView
android:id="#+id/scelta_spessore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_peso_linea"
android:padding="15dp"
android:clickable="true"
android:background="?attr/selectableItemBackgroundBorderless"/>
<ImageView
android:id="#+id/undo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_undo"
android:padding="15dp"
android:clickable="true"
android:background="?attr/selectableItemBackgroundBorderless"/>
<ImageView
android:id="#+id/redo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_redo"
android:padding="15dp"
android:clickable="true"
android:background="?attr/selectableItemBackgroundBorderless"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
I have two problems:
The drawing does it for me behind the image and not above
imagebug
The background of the image is not full screen with margins.
How should I do?
Thanks
Cris

Related

How to change shape by controlling it from points and line

I have a trapezoid shape created in custom view using below code.
#Override
protected void onDraw(Canvas canvas) {
trapezoidPath.moveTo(0,0);
trapezoidPath.lineTo(getWidth() ,0);
trapezoidPath.lineTo(getWidth() , altitude);
trapezoidPath.lineTo(0,getHeight());
trapezoidPath.lineTo(0,0);
trapezoidPath.close();
canvas.drawPath(trapezoidPath,paintTrapezoid);
}
The drawn shape looks like this.
I want to move (0,height) point to top until trapezoid shape become a rectangle. After that I want to move bottom line up until shape become a line.
Is there any way to access created path lines and it's point and manipulate them to achieve what I want ? If not how can I achieve this ?
I have to animate this shape base on user response. Thank you.
Use an ObjectAnimator to change the variables you use in onDraw. Below is an example of how you could implement this.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TrapezoidView trapezoidView = findViewById(R.id.trapezoid);
final Button resetButton = findViewById(R.id.btn_reset);
resetButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
trapezoidView.reset();
}
});
final Button animateButton = findViewById(R.id.btn_animate);
animateButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
animateButton.setEnabled(false);
resetButton.setEnabled(false);
trapezoidView.toNewState();
}
});
trapezoidView.setListener(new TrapezoidView.TrapezoidListener() {
#Override
public void onNewState() {
animateButton.setEnabled(true);
resetButton.setEnabled(true);
}
});
}
}
TrapezoidView.java
public class TrapezoidView extends View {
public interface TrapezoidListener {
void onNewState();
}
public static final int TRAPEZOID_STATE = 0;
public static final int RECTANGLE_STATE = 1;
public static final int LINE_STATE = 2;
private int mState = TRAPEZOID_STATE;
private Paint mTrapezoidPaint;
private Path mTrapezoidPath = new Path();
private int mAnimationDuration = 5000; // 5 s in millis
private float mRectangleHeight = dpTopx(200);
private float mAltitude = mRectangleHeight;
private TrapezoidListener mListener;
public TrapezoidView(Context context, AttributeSet attrs) {
super(context, attrs);
mTrapezoidPaint = new Paint();
mTrapezoidPaint.setColor(Color.BLACK);
mTrapezoidPaint.setStrokeWidth(5.0f);
mTrapezoidPaint.setStyle(Paint.Style.STROKE);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mTrapezoidPath.reset();
if (mState == TRAPEZOID_STATE) {
mAltitude = getHeight();
}
mTrapezoidPath.moveTo(0, 0);
mTrapezoidPath.lineTo(getWidth(), 0);
if (mState == LINE_STATE) {
mTrapezoidPath.lineTo(getWidth(), mAltitude);
mTrapezoidPath.lineTo(0, mAltitude);
} else {
mTrapezoidPath.lineTo(getWidth(), mRectangleHeight);
mTrapezoidPath.lineTo(0, mAltitude);
}
mTrapezoidPath.lineTo(0, 0);
mTrapezoidPath.close();
canvas.drawPath(mTrapezoidPath, mTrapezoidPaint);
}
private float dpTopx(int dp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
public float getAltitude() {
return mAltitude;
}
public void setAltitude(float altitude) {
this.mAltitude = altitude;
invalidate();
}
public void reset() {
mState = TRAPEZOID_STATE;
mRectangleHeight = dpTopx(200);
mAltitude = mRectangleHeight;
invalidate();
}
public void setListener(TrapezoidListener listener) {
mListener = listener;
}
public void toNewState() {
if (mState == LINE_STATE) {
mListener.onNewState();
return;
}
float start;
float target;
final int targetState = mState == TRAPEZOID_STATE ? RECTANGLE_STATE : LINE_STATE;
if (targetState == RECTANGLE_STATE) {
start = getHeight();
target = mRectangleHeight;
} else {
start = mAltitude;
target = 0.0f;
}
ObjectAnimator stateAnimation = ObjectAnimator.ofFloat(TrapezoidView.this, "Altitude", start);
stateAnimation.setFloatValues(target);
stateAnimation.setDuration(mAnimationDuration);
stateAnimation.addListener(
new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
mState = targetState;
}
#Override
public void onAnimationEnd(Animator animation) {
mListener.onNewState();
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
}
);
stateAnimation.start();
}
}
activity_main.xml
<LinearLayout 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:orientation="vertical"
android:padding="50dp"
tools:context="test.example.MainActivity">
<test.example.TrapezoidView
android:id="#+id/trapezoid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.9" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.1"
android:orientation="horizontal">
<Button
android:id="#+id/btn_animate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Animate!" />
<Button
android:id="#+id/btn_reset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Reset" />
</LinearLayout>
</LinearLayout>

Android - Bitmap - Fatal Signal 11 (SIGSEGV), code 1

I have a project where I need a custom canvas (white sheet) like a view.
The activity will have two divisions
The aforementioned canvas.
A list/recycler view with images (ignore the temporary LinearLayout instead of list/recycler view)
So when I click on an Image. This image will get transferred to the canvas. Where user can drag, scale, rotate or do all of these together to that image. This canvas should support up to 4-5 images at the same time.
I would like to know if there is any better alternative or I am going to the right direction.
If I am going to the right direction. Please help me on this issue.
A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x180 in tid 18318 (odrob_sylvester)
Here is my Activity Class (CanvasActivity.java)
public class CanvasActivity extends AppCompatActivity {
private static final String TAG = CanvasActivity.class.getSimpleName();
private WodrobView canvas;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_canvas);
canvas = (WodrobView) findViewById(R.id.canvas);
}
public void img1click(View view) {
Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.wodrob_1);
Product product = new Product(image);
Details details = new Details("Wodrob_1", "123", 123);
product.setDetails(details);
WodrobHandler.addObjectToWODROB(product);
Log.d(TAG, "img1click called");
canvas.updateCanvas();
}
}
activity_canvas.xml
<LinearLayout 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:orientation="vertical"
tools:context="com.example.wodrob.wodrob_sylvester.CanvasActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/card_margin_horizontal"
android:background="#ffffff"
android:elevation="#dimen/canvas_elevation">
<com.example.wodrob.wodrob_sylvester.widget.WodrobView
android:id="#+id/canvas"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="250dp" />
</FrameLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/card_margin_horizontal"
android:foreground="?attr/selectableItemBackground"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="150dp"
android:clickable="true"
android:scaleType="fitXY"
android:background="#color/black"
android:padding="1dp"
android:onClick="img1click"
android:src="#drawable/wodrob_1" />
<ImageView
android:layout_width="match_parent"
android:layout_height="150dp"
android:scaleType="fitXY"
android:background="#color/black"
android:padding="1dp"
android:src="#drawable/wodrob_2" />
<ImageView
android:layout_width="match_parent"
android:layout_height="150dp"
android:scaleType="fitXY"
android:background="#color/black"
android:padding="1dp"
android:src="#drawable/wodrob_3" />
<ImageView
android:layout_width="match_parent"
android:layout_height="150dp"
android:scaleType="fitXY"
android:background="#color/black"
android:padding="1dp"
android:src="#drawable/wodrob_4" />
</LinearLayout>
</ScrollView>
</LinearLayout>
Custom widget canvas (WodrobView.java)
public class WodrobView extends View {
private static final String TAG = WodrobView.class.getSimpleName();
private Context mContext;
public WodrobView(Context context) {
super(context);
mContext = context;
}
public WodrobView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
public WodrobView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
}
#Override
public void draw(final Canvas canvas) {
super.draw(canvas);
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
drawingImages(canvas);
}
});
}
private void drawingImages(Canvas canvas){
Map<Point, Product> drawMap = WodrobHandler.getObjects();
for (Point point : drawMap.keySet()){
Product product = drawMap.get(point);
if (product.isAdded()) {
Log.w(TAG, product.getDetails().getName() + " is already added!");
continue;
}
Bitmap bitmap = product.getBitmap();
Bitmap bitmapTemp = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth() / 2, bitmap.getHeight() / 2, false);
canvas.drawBitmap(bitmapTemp, point.x, point.y, new Paint(Paint.ANTI_ALIAS_FLAG));
}
}
public void updateCanvas() {
invalidate();
}
}
A WodrobHandler.java
public class WodrobHandler implements WodrobHelper {
interface WodrobHelper {
Point[] POINTS = new Point[]{
new Point(10, 10),
new Point(10, 10),
new Point(10, 10),
new Point(10, 10)
};
}
private static final String TAG = WodrobHandler.class.getSimpleName();
private static Map<Point, Product> objects = new HashMap<>();
private static short position = 0;
public static boolean addObjectToWODROB(Product product){
if (position >= 4 || position < 0){
Set<Point> pointSet = objects.keySet();
for (Point point:POINTS) {
short flag = 0;
for (Point point1:pointSet) {
if (point.equals(point1.x, point1.y))
flag++;
}
if (flag == 0) {
objects.put(point, product);
return true;
}
}
Log.e(TAG, "Invalid position or full");
return false;
} else {
objects.put(POINTS[position++], product);
return true;
}
}
public static boolean removeObjectFromWODROB(Product product){
if (!objects.containsValue(product)){
Log.e(TAG, "No such product to remove");
return false;
}
objects.remove(product.getPoint());
return true;
}
public static Map<Point, Product> getObjects() {
return objects;
}
public static void setObjects(Map<Point, Product> objects) {
WodrobHandler.objects = objects;
}
}
Product.java
public class Product {
private Bitmap bitmap;
private Details details;
Point point = null;
private boolean added = false;
public boolean isAdded() {
return added;
}
public void setAdded(boolean added) {
this.added = added;
}
public Product(Bitmap bitmap) {
//Getting bitmap from drawable resource
this.bitmap = bitmap;
}
public Bitmap getBitmap() {
return bitmap;
}
public Details getDetails() {
return details;
}
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
public void setDetails(Details details) {
this.details = details;
}
}
Details.java
public class Details {
private String name, id;
private int cost;
public Details(String name, String id, int cost) {
this.name = name;
this.id = id;
this.cost = cost;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
public int getCost() {
return cost;
}
}
I think objects in WodrobHandler is empty. Where are code you add element?
You have to convert bitmap to mutable and avoid create bitmap in onDraw. Create it on Construtor. Code create bitmap mutable:
Bitmap. createScaledBitmap(souce,souce.getWidth(),source.getHeight,false);

android ValueAnimator Performance issues,get lag after some work

I was developing user "eluleci" (https://gist.github.com/eluleci/6e0d02c766b27f6a5253) code
it's rippleTuch for preLilop
ok , it's extend Button class for do it,
when we have one button in our layout, all things work good and animation work smooth,
but when we add more than one button , like 5 button, by touch them the animation on the buttons get lag and not smooth!!
I cant understand what's the problem? Memory issues? and how can I fix it?can anyone knew where is the problem?
thank you for your attention
here is my code:
public class MehDiRippleButton extends Button {
#Override
public boolean isInEditMode() {
return true;
}
Paint paint=new Paint();
private static final int AnimDuration = 9000;
private TouchEffectAnimator touchEffectAnimator;
public MehDiRippleButton(Context context) {
super(context);
init();
}
public MehDiRippleButton(Context context, AttributeSet attrs) {
super(context, attrs);
allocated_TuchEffectAnimator();
TypedArray typedArray_MehDi_rippleButton_style = context.obtainStyledAttributes(attrs,R.styleable.MehDi_rippleButton_style);
CharSequence charSequence_buttonColor =typedArray_MehDi_rippleButton_style.getString(R.styleable.MehDi_rippleButton_style_MehDi_buttonColor);
paint.setColor(Color.parseColor(charSequence_buttonColor.toString()));
touchEffectAnimator.setStroke(paint);
CharSequence charSequence_rippleColor =typedArray_MehDi_rippleButton_style.getString(R.styleable.MehDi_rippleButton_style_MehDi_rippleColor);
if(charSequence_rippleColor!=null) {
touchEffectAnimator.setEffectColor(Color.parseColor(charSequence_rippleColor.toString()),Color.parseColor(charSequence_buttonColor.toString()));
}else touchEffectAnimator.setEffectColor(Color.LTGRAY,Color.WHITE);
typedArray_MehDi_rippleButton_style.recycle();
init();
}
private void allocated_TuchEffectAnimator(){
touchEffectAnimator = new TouchEffectAnimator(this);
}
private void init() {
touchEffectAnimator.setHasRippleEffect(true);
touchEffectAnimator.setAnimDuration(AnimDuration);
touchEffectAnimator.setClipRadius(0);
setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
}
});
}
#Override
public boolean onTouchEvent(final MotionEvent event) {
touchEffectAnimator.onTouchEvent(event);
return super.onTouchEvent(event);
}
#Override
protected void onDraw(Canvas canvas) {
touchEffectAnimator.onDraw(canvas);
super.onDraw(canvas);
}
}
and :
(in this class occurred the problem):
public class TouchEffectAnimator {
float u=0;
private static final int fadeout_time_helper=29;
private static final int tuchUp_time_helper=14;
private final int EASE_ANIM_DURATION = 2000;
private final int RIPPLE_ANIM_DURATION = 3000;
private final int MAX_RIPPLE_ALPHA = 255;
private View mView;
private int mClipRadius;
private boolean hasRippleEffect = false;
private int animDuration = EASE_ANIM_DURATION;
private int requiredRadius;
private float mDownX;
private float mDownY;
private float mRadius;
private int mCircleAlpha = MAX_RIPPLE_ALPHA;
private int mRectAlpha = 0;
private Paint mCirclePaint = new Paint();
private Paint mStrokePaint = new Paint();
private Paint mRectPaint = new Paint();
private Path mCirclePath = new Path();
private Path mRectPath = new Path();
private boolean isTouchReleased = false;
private boolean isAnimatingFadeIn = false;
/**
*
*
* */
private Animation.AnimationListener animationListener = new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
isAnimatingFadeIn = true;
}
#Override
public void onAnimationEnd(Animation animation) {
isAnimatingFadeIn = false;
if (isTouchReleased){
setStroke(mStrokePaint);
fadeOutEffect();
}
}
#Override
public void onAnimationRepeat(Animation animation) {
}
};
public TouchEffectAnimator(View mView) {
this.mView = mView;
}
public void setHasRippleEffect(boolean hasRippleEffect) {
this.hasRippleEffect = hasRippleEffect;
if (hasRippleEffect) animDuration = RIPPLE_ANIM_DURATION;
}
public void setAnimDuration(int animDuration) {
this.animDuration = animDuration;
}
public void setEffectColor(int effectColor,int buttonColor) {
mCirclePaint.setColor(effectColor);
mCirclePaint.setAlpha(mCircleAlpha);
mRectPaint.setColor(effectColor);
mRectPaint.setAlpha(mRectAlpha);
mStrokePaint.setColor(buttonColor);
}
public void setClipRadius(int mClipRadius) {
this.mClipRadius = mClipRadius;
}
public void onTouchEvent(final MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
isTouchReleased = true;
Drawable background = mView.getBackground();
if (background instanceof ShapeDrawable) {
((ShapeDrawable)background).getPaint().setStrokeWidth(0);
Log.e("fdsfsfd","fdsfdsfdsf");
} else if (background instanceof GradientDrawable) {
//((GradientDrawable)background).setS
Log.e("qqq","qqq");
}
ValueGeneratorAnim valueGeneratorAnim = new ValueGeneratorAnim(new InterpolatedTimeCallback() {
#Override
public void onTimeUpdate(float interpolatedTime) {
if (hasRippleEffect)
mRadius = requiredRadius * interpolatedTime +u;
mRectAlpha = (int) (interpolatedTime * MAX_RIPPLE_ALPHA);
mView.invalidate();
}
});
valueGeneratorAnim.setInterpolator(new DecelerateInterpolator());
valueGeneratorAnim.setDuration(animDuration/tuchUp_time_helper);
valueGeneratorAnim.setAnimationListener(animationListener);
mView.startAnimation(valueGeneratorAnim);
if (!isAnimatingFadeIn) {
setStroke(mStrokePaint);
fadeOutEffect();
}
} else if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
// gets the bigger value (width or height) to fit the circle
requiredRadius = mView.getWidth() >= mView.getHeight() ? mView.getWidth() : mView.getHeight();
final int requiredRadius2 = mView.getWidth() < mView.getHeight() ? mView.getWidth() : mView.getHeight();
noStroke(mStrokePaint);
requiredRadius *= 1.2;
Log.e("req ", "" + requiredRadius);
isTouchReleased = false;
mDownX = event.getX();
mDownY = mView.getMeasuredHeight()/2;
Drawable background = mView.getBackground();
if (background instanceof ShapeDrawable) {
((ShapeDrawable)background).getPaint().setStrokeWidth(0);
Log.e("fdsfsfd","fdsfdsfdsf");
} else if (background instanceof GradientDrawable) {
//((GradientDrawable)background).setS
Log.e("qqq","qqq");
}
mCircleAlpha = MAX_RIPPLE_ALPHA;
mRectAlpha = 0;
ValueGeneratorAnim valueGeneratorAnim = new ValueGeneratorAnim(new InterpolatedTimeCallback() {
#Override
public void onTimeUpdate(float interpolatedTime) {
Log.e("1 ", "" + 1);
if (hasRippleEffect)
mRadius = requiredRadius * interpolatedTime+(float)(requiredRadius2/1.5);
u=mRadius;
Log.e("mRa ", "" + mRadius);
Log.e("int ", "" + interpolatedTime);
mRectAlpha = (int) (interpolatedTime * MAX_RIPPLE_ALPHA);
mView.invalidate();
}
});
Log.e("222 ", "" + 222);
valueGeneratorAnim.setInterpolator(new DecelerateInterpolator());
valueGeneratorAnim.setDuration(animDuration);
valueGeneratorAnim.setAnimationListener(animationListener);
mView.startAnimation(valueGeneratorAnim);
}
}
public void onDraw(final Canvas canvas) {
if (hasRippleEffect) {
mCirclePath.reset();
mCirclePaint.setAlpha(mCircleAlpha);
mCirclePath.addRoundRect(new RectF(0, 0, mView.getWidth(), mView.getHeight()),
mClipRadius, mClipRadius, Path.Direction.CW);
canvas.clipPath(mCirclePath);
canvas.drawCircle(mDownX, mDownY, mRadius, mCirclePaint);
}
mRectPath.reset();
if (hasRippleEffect && mCircleAlpha != 255) mRectAlpha = mCircleAlpha / 2;
mRectPaint.setAlpha(mRectAlpha);
canvas.drawRoundRect(new RectF(0, 0, mView.getWidth(), mView.getHeight()), mClipRadius,mClipRadius, mRectPaint);
}
private void fadeOutEffect() {
ValueGeneratorAnim valueGeneratorAnim = new ValueGeneratorAnim(new InterpolatedTimeCallback() {
#Override
public void onTimeUpdate(float interpolatedTime) {
mCircleAlpha = (int) (MAX_RIPPLE_ALPHA - (MAX_RIPPLE_ALPHA * interpolatedTime));
mRectAlpha = mCircleAlpha;
mView.invalidate();
}
});
valueGeneratorAnim.setDuration(animDuration / fadeout_time_helper); /**change anim fade out time*/
mView.startAnimation(valueGeneratorAnim);
}
class ValueGeneratorAnim extends Animation {
private InterpolatedTimeCallback interpolatedTimeCallback;
ValueGeneratorAnim(InterpolatedTimeCallback interpolatedTimeCallback) {
this.interpolatedTimeCallback = interpolatedTimeCallback;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
this.interpolatedTimeCallback.onTimeUpdate(interpolatedTime);
}
}
interface InterpolatedTimeCallback {
public void onTimeUpdate(float interpolatedTime);
}
public void setStroke(Paint mStrokePaint){
GradientDrawable gradiant_withStroke = new GradientDrawable();
gradiant_withStroke.setColor(mStrokePaint.getColor());
gradiant_withStroke.setStroke(8, Color.parseColor("#00000000"));
mView.setBackgroundDrawable(gradiant_withStroke);
}
public void noStroke(Paint mStrokePaint){
GradientDrawable gradiant_withStroke = new GradientDrawable();
gradiant_withStroke.setColor(mStrokePaint.getColor());
gradiant_withStroke.setStroke(0, Color.parseColor("#00000000"));
mView.setBackgroundDrawable(gradiant_withStroke);
}
}
and activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical">
<com.example.mahdi.myapplication.MehDiRippleButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/view2"
android:layout_gravity="center_horizontal"
android:text="Ripple Tuch"
app:MehDi_rippleColor="#cf030a"
app:MehDi_buttonColor="#ff2c25"
/>
<com.example.mahdi.myapplication.MehDiRippleButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/view34"
android:text="Produce By"
app:MehDi_rippleColor="#f7f336"
app:MehDi_buttonColor="#d3ce00"
/>
<com.example.mahdi.myapplication.MehDiRippleButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/view"
android:layout_gravity="center_horizontal"
android:text="MehDi"
app:MehDi_rippleColor="#00930e"
app:MehDi_buttonColor="#00b909"
/>
<com.example.mahdi.myapplication.MehDiRippleButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/view3"
android:layout_gravity="center_horizontal"
android:text="NazaRi"
app:MehDi_rippleColor="#303dd3"
app:MehDi_buttonColor="#7688e5"
/>
<com.example.mahdi.myapplication.MehDiRippleButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/view23"
android:layout_gravity="center_horizontal"
android:text="؛)"
app:MehDi_rippleColor="#cf0584"
app:MehDi_buttonColor="#ff0fb6"
/>
<com.example.mahdi.myapplication.MehDiRippleButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/viehw23"
android:layout_gravity="center_horizontal"
android:text=":D"
app:MehDi_rippleColor="#a2a3a2"
app:MehDi_buttonColor="#dadbda"
/>
You need to dig out the Handler which executes most of these animation calls, and invoke handler.removeCallbacksAndMessages(null); and that will take care of some of the lag.
Because most probably, when you finish and reenter the said activity, it works good and fast as when first ran. This can be caused by having alot of Threads or Handler messages that have ended their lifecycle but haven't been removed due to being dead.

Draw and animate a dashed line

I have a fullscreen activity that should look like this:
where the big white circle would have some text, I've already done it, but the problem is that I don't know how to do that dashed lines between the icons, also they want a little animation in the icons, so I assumed that each one should be a separate view, so far I've done this (it doesn't need to look exactly the same):
So, how could I draw that lines? Also if I could make that dashes to "run" acrross the lines would be awesome.
this is my xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/rlt_welcome"
android:layout_weight="9"
android:background="#drawable/bg"
>
<RelativeLayout
android:layout_width="0dp"
android:layout_weight="2"
android:orientation="vertical"
android:padding="10dp"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:id="#+id/img_youtube"
android:src="#drawable/youtube_circle"
android:layout_marginTop="60dp"
android:layout_marginRight="60dp"
android:layout_height="wrap_content"
/>
<ImageView
android:layout_width="wrap_content"
android:src="#drawable/tablet_circle"
android:layout_height="wrap_content"
android:layout_above="#+id/img_stats"
android:layout_marginRight="30dp"
android:layout_below="#+id/img_youtube"
/>
<ImageView
android:layout_width="wrap_content"
android:id="#+id/img_stats"
android:src="#drawable/stats_circle"
android:layout_height="wrap_content"
android:layout_marginRight="70dp"
android:layout_marginBottom="20dp"
android:layout_alignParentBottom="true"/>
<ImageView
android:id="#+id/img_iphone"
android:layout_width="wrap_content"
android:src="#drawable/iphone_circle"
android:layout_height="wrap_content"
android:layout_marginLeft="60dp"
/>
<ImageView
android:layout_width="wrap_content"
android:src="#drawable/imac_circle"
android:layout_height="wrap_content"
android:layout_below="#+id/img_iphone"
android:layout_marginLeft="70dp"
android:layout_marginTop="-30dp"
/>
<ImageView
android:layout_width="wrap_content"
android:src="#drawable/webcam_circle"
android:layout_height="wrap_content"
android:layout_marginLeft="60dp"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_weight="5"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center_vertical"
android:padding="40dp"
android:textSize="25sp"
android:textColor="#color/text1"
android:layout_margin="20dp"
android:text="Bienvenido"
android:background="#drawable/flat_circle"
android:id="#+id/txt_welcome"
android:layout_centerInParent="true" />
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="match_parent"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/arrow_circle"
android:id="#+id/img_arrow"
android:layout_alignParentTop="true"
android:layout_marginRight="60dp"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/news_circle"
android:layout_below="#+id/img_arrow"
android:layout_marginTop="-90dp"
android:layout_marginRight="2dp"
android:layout_marginLeft="70dp"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/line_circle"
android:id="#+id/img_line"
android:layout_below="#+id/img_arrow"
android:layout_marginTop="-10dp"
android:layout_marginRight="70dp"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/money_circle"
android:layout_below="#+id/img_line"
android:layout_marginRight="6dp"
android:layout_marginTop="-70dp"
android:layout_marginLeft="70dp"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/mouse_circle"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginRight="80dp"
/>
</RelativeLayout>
</LinearLayout>
Please check this, may be this will help you
http://www.rengelbert.com/tutorial.php?id=182
How do I get this work, I made a new activity that holds a Canvas controller, and place the bitmaps on the canvas and draw the lines between them with this, I didn't use any external library:
Hope someone could reuse some code and not only been told to google it.
MainActivty.java
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
relativeMainActivity = (RelativeLayout) findViewById(R.id.rlt_main);
DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
final int heightS = dm.heightPixels;
final int widthS = dm.widthPixels;
Log.d("MainActvitiy", "widht:" + widthS);
myPanel = new Panel(getApplicationContext(),this,widthS, heightS);
relativeMainActivity.addView(myPanel);
RelativeLayout RR = new RelativeLayout(this);
RR.setGravity(Gravity.CENTER);
relativeMainActivity.addView(RR,400,150);
RR.setX(0);
LayoutInflater myInflater = (LayoutInflater) getApplicationContext().getSystemService(getApplicationContext().LAYOUT_INFLATER_SERVICE);
}
Panel.java
public class Panel extends SurfaceView implements SurfaceHolder.Callback {
public MainThread thread;
private Background background;
private CircleManager CM;
public int ScreenWidth;
public int Screenheigt;
private CircleIcon icon1;
private CircleIcon icon2;
private CircleIcon icon3;
//and so on
public MainActivity myMain;
public Panel(Context context, MainActivity _main, int width , int height) {
super(context);
getHolder().addCallback(this);
this.myMain = _main;
this.ScreenWidth=width;
this.Screenheigt=height;
thread = new MainThread(getHolder(),this);
background = new Background(BitmapFactory.decodeResource(getResources(), R.drawable.bg), Screenheigt, this);
CM = new CircleManager( this,context,ScreenWidth);
CM.setScreen(ScreenWidth, Screenheigt);
SetIcons();
CM.setManager();
setFocusable(true);
}
void SetIcons()
{
icon1 = new CircleIcon(BitmapFactory.decodeResource(getResources(),R.drawable.circle_iphone),39,40);
icon2 = new CircleIcon(BitmapFactory.decodeResource(getResources(),R.drawable.circle_chat),280,40);
icon3 = new CircleIcon(BitmapFactory.decodeResource(getResources(),R.drawable.circle_youtube),60,200);
//and so on
icon1.myConnections.add(2);
icon1.myConnections.add(3);
icon2.myConnections.add(15);
icon3.myConnections.add(4);
icon3.myConnections.add(5);
//and so on
CM.iconsList.add(icon1);
CM.iconsList.add(icon2);
CM.iconsList.add(icon3);
//and so on
}
void Draw(Canvas canvas){
if (canvas!=null)
{
background.draw(canvas);
CM.draw(canvas);
iconEvent.draw(canvas);
}
}
void Update(float dt)
{
CM.Update(dt);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
boolean retry = true;
while (retry)
{
try
{
thread.join();
retry=false;
}
catch (InterruptedException e)
{
}
}
}
}
Background.java
public class Background {
Bitmap BackBitmap;
int x,y;
int ScreenHeight;
Panel root_panel;
public Background(Bitmap bitmap , int Screen_h, Panel _panel) {
this.BackBitmap = bitmap;
this.x=0;
this.y=0;
this.ScreenHeight=Screen_h;
root_panel =_panel;
}
public void draw(Canvas canvas)
{
canvas.drawBitmap(BackBitmap,x,y, null);
}
}
CircleIcon.java
public class CircleIcon {
private Bitmap bitmap;
private int x;
private int y;
CircleManager circManager;
ArrayList<Integer> myConnections;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y=y;
}
public CircleIcon(Bitmap icon, int x, int y) {
bitmap=icon;
this.x=x;
this.y=y;
myConnections = new ArrayList<>();
}
public ArrayList<Integer> getMyConnections() {
return myConnections;
}
public void setMyConnections(ArrayList<Integer> myConnections) {
this.myConnections = myConnections;
}
public void setManager(CircleManager icManager) {
circManager = icManager;
}
public Bitmap getBitmap()
{
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, x, y, null);
}
public void update()
{
// x=+1; example
}
}
CircleManager.java
public class CircleManager {
Bitmap icons;
int screenWidth;
int hour;
int min;
Context myContext;
int ScreenWidht;
public Panel myPanel;
public ArrayList<CircleIcon> iconsList;
public CircleManager(Panel _Panel, Context context,int screenW) {
this.myPanel = _Panel;
this.screenWidth = screenW;
this.myContext = context;
iconsList = new ArrayList<CircleIcon>();
}
public void setScreen(int screenWidth, int screenHeight)
{
this.ScreenWidht=screenWidth;
}
public void draw(Canvas canvas)
{
drawLines(canvas);
for(CircleIcon myIcon: iconsList)
{
myIcon.draw(canvas);
}
}
public void Update(float dt)
{
//some animation updates
}
public void drawLines(Canvas canvas)
{
Paint mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(2);
mPaint.setPathEffect(new DashPathEffect(new float[]{7, 5}, 0));
for (CircleIcon myIcon: iconsList)
{
for( int connectedIcon: myIcon.getMyConnections())
{
Path mPath;
mPath = new Path();
mPath.moveTo(myIcon.getX()+myIcon.getBitmap().getWidth()/2, myIcon.getY()+myIcon.getBitmap().getHeight()/2);
mPath.lineTo(iconsList.get(connectedIcon-1).getX()+myIcon.getBitmap().getWidth()/2, iconsList.get(connectedIcon-1).getY()+myIcon.getBitmap().getHeight()/2);
canvas.drawPath(mPath, mPaint);
}
}
}
public void setManager()
{
for(CircleIcon myIcon: iconsList)
{
myIcon.setManager(this);
}
}
}

Drawing removes on switching between fragments

I add 2 fragments in tab host.In second fragment i can do some drawing. When i switch between these two fragments, my drawing in second fragment is removed.I don't know why??
This is second fragment.
public class DrawingFragment extends BaseFragment implements android.view.View.OnClickListener {
private Context context = null;
private Bitmap backGroundBitmap = null;
private DrawingViewHolder viewHolder = null;
/**
*
*/
#Override
public void onAttach(Activity arg0) {
super.onAttach(arg0);
this.context=arg0;
}
public DrawingFragment() {
}
public DrawingFragment(Bitmap bitmap) {
this.backGroundBitmap = bitmap;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.drawing_dialog, container,false);
viewHolder = new DrawingViewHolder();
viewHolder.initUiContents(view);
return view;
}
/**
*
* #author Qandil
*
*/
private class DrawingViewHolder{
private Button btnDoneDrawing = null;
private Button btnEraserDrawing = null;
private Button btnPencilDrawing = null;
private Button btnDeleteDrawing = null;
private LinearLayout llDrawingMain = null;
private DrawView drawingView = null;
private void initUiContents(View view){
btnDoneDrawing = (Button) view.findViewById(R.id.btn_drawing_done);
btnEraserDrawing = (Button) view.findViewById(R.id.btn_drawing_eraser);
btnPencilDrawing = (Button) view.findViewById(R.id.btn_drawing_pencil);
btnDeleteDrawing = (Button) view.findViewById(R.id.btn_drawing_delete);
llDrawingMain = (LinearLayout) view.findViewById(R.id.ll_drawing_dialog_main);
drawingView = (DrawView)view.findViewById(R.id.custom_dv2);
btnDoneDrawing.setOnClickListener(DrawingFragment.this);
btnEraserDrawing.setOnClickListener(DrawingFragment.this);
btnPencilDrawing.setOnClickListener(DrawingFragment.this);
btnDeleteDrawing.setOnClickListener(DrawingFragment.this);
Drawable dr = new BitmapDrawable(backGroundBitmap);
llDrawingMain.setBackgroundDrawable(dr);
}
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_drawing_done:
((CaseActivity) getActivity()).popFragments();
break;
case R.id.btn_drawing_delete:
((CaseActivity) getActivity()).popFragments();
break;
default:
break;
}
}
/* (non-Javadoc)
* #see android.support.v4.app.Fragment#onDestroyView()
*/
#Override
public void onDestroyView() {
super.onDestroyView();
}
/* (non-Javadoc)
* #see android.support.v4.app.Fragment#onDetach()
*/
#Override
public void onDetach() {
super.onDetach();
}
}
drawing_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ll_drawing_dialog_main"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/ll_drawing_dialog"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/img_draw_photo_bg"
android:orientation="vertical" >
<RelativeLayout
android:id="#+id/top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/img_top_bar" >
<TextView
android:id="#+id/tv_draw_picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="#string/tv_draw_picture"
android:textColor="#ffffff"
android:textSize="18sp"
android:textStyle="bold" />
</RelativeLayout>
<LinearLayout
android:id="#+id/ll_header_drawing_dialog"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/img_top_bar"
android:gravity="center" >
<Button
android:id="#+id/btn_drawing_done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/img_drawing_done" />
<Button
android:id="#+id/btn_drawing_eraser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:background="#drawable/img_drawing_eraser" />
<Button
android:id="#+id/btn_drawing_pencil"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:background="#drawable/img_drawing_pencil" />
<Button
android:id="#+id/btn_drawing_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:background="#drawable/img_drawing_dlt" />
</LinearLayout>
<RelativeLayout
android:id="#+id/rlt_drawing_component"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<view
android:id="#+id/custom_dv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
class="com.avhl.view.activity.DrawView"
android:background="#00000000" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
DrawView.java
public class DrawView extends View{
private Bitmap cache;
private Queue<PointF> points;
private PointF from;
private Context context;
private Paint paint ;
public DrawView(Context context,AttributeSet attr) {
super(context,attr);
this.context=context;
points = new ConcurrentLinkedQueue<PointF>();
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(8);
paint.setColor(Color.GRAY);
paint.setDither(true); // set the dither to true
paint.setStyle(Paint.Style.FILL_AND_STROKE); // set to STOKE
paint.setStrokeJoin(Paint.Join.ROUND); // set the join to round you want
paint.setStrokeCap(Paint.Cap.ROUND); // set the paint cap to round too
setFocusable(true);
setFocusableInTouchMode(true);
}
/***
* on touch event
*/
#Override
public boolean onTouchEvent(MotionEvent evt) {
setPressed(true);
int pointerIndex = ((evt.getAction() & MotionEvent.ACTION_POINTER_ID_MASK)
>> MotionEvent.ACTION_POINTER_ID_SHIFT);
int pointerId = evt.getPointerId(pointerIndex);
if(pointerId==0){
switch (evt.getAction()) {
case MotionEvent.ACTION_DOWN:
from = new PointF(evt.getX(), evt.getY());
break;
case MotionEvent.ACTION_MOVE:
points.add(new PointF(evt.getX(), evt.getY()));
invalidate();
break;
case MotionEvent.ACTION_UP:
break;
default:
from = null;
}
}else{
return false;
}
return true;
}
/**
*
* #param systemCanvas
*/
#Override
public void onDraw(Canvas systemCanvas) {
int w = getWidth();
int h = getHeight();
if (w == 0 || h == 0)
return;
if (cache == null)
cache = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
// Draw on the cache
Canvas canvas = new Canvas(cache);
drawPoints(points, canvas, paint);
// Draw the cache with the system canvas
systemCanvas.drawBitmap(cache, 0, 0, paint);
}
/*
* for drawing line or dot
*/
private void drawPoints(Queue<PointF> points, Canvas canvas, Paint paint) {
if (from == null)
return;
PointF to;
while ((to = points.poll()) != null) {
canvas.drawLine(from.x, from.y, to.x, to.y, paint);
from = to;
}
}
}
In MianActivity i simply replace DrawingFragment tab with my first fragment by calling ft.replace() in on tab changed.
You can try calling Fragment.setRetainInstance(true) in the onCreate of your Fragment. This ensure the same fragment instance will be reused instead of creating a new one.
Without some code to show what you are doing, it is difficult to be more helpful

Categories

Resources