How Can I store a custom view into the Bitmap object? For example using following code we can store the imageView object into the bitmap object.
Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
But if I create a custom view using the following code, How Can I store the custom view into the Bitmap object?
public class MainActivity extends Activity {
Custom custom;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//How Can I store the `custom` object into the `Bitmap` object? Can I do this?
}}
class Custom extends View{
Paint paint;
Custom(Context context){
super(context);
paint = new Paint();
}
#Override
protected void onDraw(Canvas canvas) {
//Some operations
}
}
there is a way to do this. you have to create a Bitmap and a Canvas and call view.draw(canvas);
here is the code:
public static Bitmap loadBitmapFromView(View v) {
Bitmap b = Bitmap.createBitmap(v.getLayoutParams().width,v.getLayoutParams().height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
v.draw(c);
return b;
}
Related
My task is to draw a shape on second activity when user clicks a button. So I tried a following code, but it doesn't work.
I have referred lot of tutorials but all they did in another View. I didn't understand the View.
MainActivity.java
public class MainActivity extends AppCompatActivity implements
View.OnClickListener {
Button draw;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
draw = findViewById(R.id.drawButton);
draw.setOnClickListener(this);
}
#Override
public void onClick(View v) {
shape = dropdown.getSelectedItem().toString();
Bundle b = new Bundle();
b.putString("shape",shape);
Intent i = new Intent(getApplicationContext(),shapes.class);
i.putExtras(b);
startActivity(i);
}
}
Shapes.java
public class shapes extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shapes);
Canvas canvas = new Canvas();
Rect rec = new Rect();
rec.top=100;
rec.left=100;
rec.bottom = rec.top + 100;
rec.right = rec.left+ 100;
Paint p = new Paint();
p.setColor(Color.GREEN);
canvas.drawRect(rec,p);
}
}
When button click you are calling intent and it will create a new Activity. You can add a simple image view to the activity main layout and then you can set your canvas drawing as follows.
ImageView imageView=(ImageView) findViewById(R.id.image);
Bitmap bitmap = Bitmap.createBitmap(100, 100,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);
Rect rec = new Rect();
rec.top=0;
rec.left=0;
rec.bottom = rec.top + 100;
rec.right = rec.left+ 100;
canvas.drawRect(rec,paint);
imageView.setImageBitmap(bitmap);
I wanted to know if it was possible to crop a picture to any other shape not just square, rectangle or circle.
Basically what I am looking for is that, the user can select a template of a png file (already present) and it cuts the picture in that shape.
Check out this code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView imageViewPreview = (ImageView) findViewById(R.id.imageview_preview);
new Thread(new Runnable() {
#Override
public void run() {
final Bitmap source = BitmapFactory.decodeResource(MainActivity.this.getResources(),
R.drawable.source);
final Bitmap mask = BitmapFactory.decodeResource(MainActivity.this.getResources(),
R.drawable.mask);
final Bitmap croppedBitmap = cropBitmap(source, mask);
runOnUiThread(new Runnable() {
#Override
public void run() {
imageViewPreview.setImageBitmap(croppedBitmap);
}
});
}
}).start();
}
private Bitmap cropBitmap(final Bitmap source, final Bitmap mask){
final Bitmap croppedBitmap = Bitmap.createBitmap(
source.getWidth(), source.getHeight(),
Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(croppedBitmap);
canvas.drawBitmap(source, 0, 0, null);
final Paint maskPaint = new Paint();
maskPaint.setXfermode(
new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
canvas.drawBitmap(mask, 0, 0, maskPaint);
return croppedBitmap;
}
}
The main function is the "cropBitmap" function. Basically it receives two bitmaps, a source and a mask, and then it "crops" the source bitmap using the mask's shape.
This is my source bitmap:
This is the mask bitmap:
And this is the result:
Also, check out this great presentation, this might help you too: Fun with Android shaders and filters
I have separate class for canvas ViewCanvas in this class I'm drawing two worlds. Here is the code:
public class ViewCanvas extends View {
private Paint paint;
private Typeface typeFace;
public ViewCanvas(Context context) {
super(context);
}
public ViewCanvas(Context context, String first, String second) {
super(context);
setDrawingCacheEnabled(true);
buildDrawingCache(true);
paint = new Paint();
typeFace = Typeface.createFromAsset(context.getAssets(), "fonts/BigNoodleTitling.ttf");
bounds = new Rect();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
paint.setColor(Color.BLACK);
paint.setTextSize(20);
paint.setTypeface(typeFace);
// Closing hardware acceleration
setLayerType(LAYER_TYPE_SOFTWARE, paint);
// Drawing first word
canvas.save();
.
.
.
.
// Drawing second world
canvas.restore();
.
.
.
.
}
}
This code works fine. I'm using this ViewCanvas in MainActivity like this:
public class MainActivity extends Activity {
private ViewCanvas viewCanvas;
private Bitmap imageForShare;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
viewCanvas = new ViewCanvas(this, first, second);
LinearLayout llCanvas = (LinearLayout) findViewById(R.id.llCanvas);
llCanvas.addView(viewCanvas);
imageForShare = viewCanvas.getDrawingCache();
}
Here imageForShare is null, and I don'n know why.
In my onClick method, viewCanvas.getDrawingCache() it's working great. imageForShare is not null and I can use it. Here is my code:
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnFacebook:
imageForShare = viewCanvas.getDrawingCache();
break;
}
}
Where is the problem, and I want imageForShare to be available in my onCreate method.
try this:
public static Bitmap loadBitmapFromView(View v) {
Bitmap b = Bitmap.createBitmap( v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
v.draw(c);
return b;
}
link
Can you not use OnStart() to get the screenshot?
The visible lifetime of an activity happens between a call to onStart()
OK, I found a solution. The creating of imageForShare in onCreate method is impossible because canvas is drawing after imageForShare is created. So i put creation of imageForShare in onWindowFocusChanged, and is working great:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
imageForShare = viewCanvas.getDrawingCache();
}
i'm trying to show a Toast message with a custom view i created.
the view has a bitmap on the background and i want to write some text on it.
if I assign the bitmap to an ImageView on the main code I manage to make it show up with Toast t; (...) t.show();
but when it's the onDraw() method of my class to assign the bitmap nothing shows up.
i checked, and my view has a size of (0, 0) when created the way i transcribe under.
help please.
Main.java
Toast t = new Toast(this);
LimitView lv = new LimitView(this);
t.setView(lv);
t.setDuration(Toast.LENGTH_LONG);
t.show();
LimitView.java
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.save();
canvas.setBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.limit));
canvas.restore();
}
try this code:
Main.java
Context context = this;
Toast t = new Toast(context);
LeftBorder lv = new LimitView(context);
t.setView(lv);
t.setDuration(Toast.LENGTH_LONG);
t.show();
LimitView.java
public class LimitView extends View {
public LimitView (Context context) {
super(context);
}
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.button_pressed), getMatrix(), new Paint());
}
}
There are several errors here.
BitmapFactory.decodeResource(getResources(), R.drawable.limit)
This is a heavy operation and should not be on view drawing phase.
canvas.setBitmap();
This method does not drawing bitmap on canvas but setting the canvas buffer to use this bitmap.
Try some thing like this:
public class MyView extends View{
private Bitmap bitmap;
public MyView(Context context) {
super(context);
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.limit);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, null);
}
}
replace this
canvas.setBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.limit));
to this:
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.button_pressed),left,top, new Paint());
here left and right are the position of the screen.
Below is my new painter app for android.
However, it does not reflect previously drawn object.
(when i touch up the screen, it lost the shape)
To, reflect previously drawn object, I tried to use 'Bitmap.createBitmap' method but it does not work.
please help me.
public class CreativePainterActivity extends Activity {
//
//private MyView vw;
Paint mPaint;
//--Variables to store the current figure info
private float _currentStartX; //where mouse first pressed
private float _currentStartY;
private float _currentEndX; //where dragged to or released
private float _currentEndY;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
setContentView(new MyView(this));
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFFFF00);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(8);
}
//view class
public class MyView extends View{
private Canvas mCanvas;
private Bitmap mBitmap;
private Paint mBitmapPaint;
Bitmap bm;
//private Paint mBitmapPaint;
public MyView(Context context){
super(context);
//ADDED
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
mBitmap = Bitmap.createBitmap(metrics.widthPixels, metrics.heightPixels, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mCanvas.drawColor(0xFFFFFFFF);
bm = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
}
public void onDraw(Canvas canvas){
//canvas.drawColor(Color.LTGRAY);
canvas.drawBitmap(bm, 0, 0, mBitmapPaint);
canvas.drawLine(_currentStartX, _currentStartY, _currentEndX, _currentEndY, mPaint);
}
//Methods for touch events
public boolean onTouchEvent(MotionEvent event){
if (event.getAction() == MotionEvent.ACTION_DOWN){
_currentStartX=event.getX();
_currentStartY=event.getY();
return true;
}
if(event.getAction() == MotionEvent.ACTION_MOVE){
_currentEndX=event.getX();
_currentEndY=event.getY();
invalidate();
return true;
}
return true;
}
}//end of the class MyView
}//end of the class CreativePainterActivity
You will need to know a bit more about how views are drawn. Your views won't preserve whatever is there on, after you draw again. So, you should somehow save whatever was there before, and redraw the old stuff, along with the new changes.
A simpler solution, would be to save the previous drawings to a Bitmap, and then draw that Bitmap again on the canvas first, and add new stuff.
The flow
onDraw(){
drawBitmap(bmp);
drawOtherStuff();
bmp = saveOnScreenBitmap();
}
So, each time you need to save the last drawn bitmap, and re-draw it. Hope it's more clear now.
Some sample tutorials:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/FingerPaint.html
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/TouchPaint.html
http://www.tutorialforandroid.com/2009/06/drawing-with-canvas-in-android.html