I'm trying to create a Custom Marker that displays text with a number equal to the example below:
Example:
But when you run the application the text is not displayed, only the red ellipse appears without a number.
My Code
InicializeMap()##
private void InicializeMap()
{
if (_googleMap == null)
{
_googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.mapMapeamento)).getMap();
LatLng pos = new LatLng(23.4555453556, 11.145315551);
MapUtils mapUtils = new MapUtils(getApplicationContext());
Bitmap bitmap = mapUtils.GetBitmapMarker();
Marker marker = _googleMap.addMarker(new MarkerOptions()
.position(pos)
.icon(BitmapDescriptorFactory.fromBitmap(bitmap)));
// check if map is created successfully or not
if (_googleMap == null)
Toast.makeText(getApplicationContext(), Mensagens.erroCriarMapa, Toast.LENGTH_SHORT).show();
}
}
My method to create the Bitmap
public Bitmap GetBitmapMarker()
{
Paint color = new Paint();
color.setTextSize(35);
color.setColor(Color.BLACK);
int px = _mContext.getResources().getDimensionPixelSize(R.dimen.map_dot_marker_size);
Bitmap mDotMarkerBitmap = Bitmap.createBitmap(px, px, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mDotMarkerBitmap);
canvas.drawText("Hello!", 30, 40, color);
Drawable shape = _mContext.getResources().getDrawable(R.drawable.shape_marker_red);
shape.setBounds(0, 0, mDotMarkerBitmap.getWidth(), mDotMarkerBitmap.getHeight());
shape.draw(canvas);
return mDotMarkerBitmap;
}
res/drawable/shape_marker_red
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<gradient
android:angle="90"
android:endColor="#f58383"
android:startColor="#ee6464" />
<stroke
android:width="1dp"
android:color="#a13939" />
</shape>
This is what I came up with.
First, declare your marker options to add the marker on the map.
MarkerOptions options = new MarkerOptions()
.position(new LatLng(GlobalApp.getInstance().getLoginUserInfo().getLatitude(),
GlobalApp.getInstance().getLoginUserInfo().getLongitude()))
.draggable(false)
.flat(false)
.icon(BitmapDescriptorFactory.fromBitmap(createStoreMarker()));
Marker tempMarker = globalGoogleMap.addMarker(options);
Add a function to inflate a layout of your specification and you can get their reference and add whatever you want.This is the place where the magic happens.
private Bitmap createStoreMarker() {
View markerLayout = getLayoutInflater().inflate(R.layout.store_marker_layout, null);
ImageView markerImage = (ImageView) markerLayout.findViewById(R.id.marker_image);
TextView markerRating = (TextView) markerLayout.findViewById(R.id.marker_text);
markerImage.setImageResource(R.drawable.ic_home_marker);
markerRating.setText(GlobalApp.getInstance().getLoginUserInfo().getStoreName());
markerLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
markerLayout.layout(0, 0, markerLayout.getMeasuredWidth(), markerLayout.getMeasuredHeight());
final Bitmap bitmap = Bitmap.createBitmap(markerLayout.getMeasuredWidth(), markerLayout.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
markerLayout.draw(canvas);
return bitmap;
}
This is the layout
store_marker_layout.xml
I am inflating
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_store_marker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusableInTouchMode="true"
android:orientation="vertical">
<TextView
android:id="#+id/marker_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="8dp"
android:text="dgdfgdfg"
android:textColor="#android:color/black"
android:textStyle="bold" />
<ImageView
android:id="#+id/marker_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="#drawable/ic_home_marker" />
</LinearLayout>
I got the following implementation and it worked.
The implementation was as follows:
MapActivity class
MapUtils mapUtils = new MapUtils(getApplicationContext());
Bitmap bitmap = mapUtils.GetBitmapMarker(getApplicationContext(), R.drawable.marker_blue, "1");
Marker marker = _googleMap.addMarker(new MarkerOptions()
.position(pos)
.icon(BitmapDescriptorFactory.fromBitmap(bitmap)));
MapUtils Class
public Bitmap GetBitmapMarker(Context mContext, int resourceId, String mText)
{
try
{
Resources resources = mContext.getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap bitmap = BitmapFactory.decodeResource(resources, resourceId);
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
// set default bitmap config if none
if(bitmapConfig == null)
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
paint.setTextSize((int) (14 * scale));
paint.setShadowLayer(1f, 0f, 1f, Color.DKGRAY);
// draw text to the Canvas center
Rect bounds = new Rect();
paint.getTextBounds(mText, 0, mText.length(), bounds);
int x = (bitmap.getWidth() - bounds.width())/2;
int y = (bitmap.getHeight() + bounds.height())/2;
canvas.drawText(mText, x * scale, y * scale, paint);
return bitmap;
}
catch (Exception e)
{
return null;
}
}
Here you go. In this method, we're creating the BitmapDescriptor with a lap number centered into one of 3 drawables.
/**
* #param lapNbr String
* #return {#link BitmapDescriptor}
*/
private BitmapDescriptor createLapBitMap(String lapNbr) {
// Determine which of the 3 icons to start from. 1 being the thinnest, 3 being the widest.
Bitmap tmp = null;
switch (lapNbr.length()) {
case 1:
tmp = BitmapFactory.decodeResource(getResources(), R.drawable.lap_icon1);
break;
case 2:
tmp = BitmapFactory.decodeResource(getResources(), R.drawable.lap_icon2);
break;
// If a dude is recording more than 999 laps, let's just shoot him. :)
default:
tmp = BitmapFactory.decodeResource(getResources(), R.drawable.lap_icon3);
break;
}
if (tmp != null) {
Bitmap.Config config = tmp.getConfig();
if (config == null) {
config = Bitmap.Config.ARGB_8888;
}
// Resource bitmpas are immutable, so we need to convert it to a mutable one.
Bitmap bm = tmp.copy(config, true);
if (bm != null) {
// Draw text to the canvas center.
Rect bounds = new Rect();
mLapIconPaint.getTextBounds(lapNbr, 0, lapNbr.length(), bounds);
int x = (bm.getWidth() - bounds.width()) / 2;
int y = ((bm.getHeight() + bounds.height()) / 2) - 10; // bump it up just a bit
Canvas c = new Canvas(bm);
c.drawText(lapNbr, x, y, mLapIconPaint);
return BitmapDescriptorFactory.fromBitmap(bm);
}
}
// Return a default bitmap with a lap circle inside of the icon.
return BitmapDescriptorFactory.fromResource(R.drawable.lap_icon1);
}
Why are you using a Bitmap here? It looks like a drawable will get the job done, and then you could programmatically change the .setText() of each variable depending on the assignment of the marker.
For example:
<Button android:id="#+id/markerButton"
android:background="#drawable/markerDrawable"/>
Then:
markerButton.setText("1");
The solution to this is now available in the Google Maps SDK for Android Utility Library
Related
I am trying to make my ImageView round. I have written the following code to make it appear round but somehow it is still showing square ImageView. [Using picasso to fetch image]
Java code:
ImageView iv = (ImageView) addLinkDialog.findViewById(R.id.group_icon_jsoup);
Picasso.with(getBaseContext()).load(GroupImageUrl).into(iv);
iv.setBackgroundResource(R.drawable.icon_img);
ImageView code:
<ImageView
android:id="#+id/group_icon_jsoup"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_gravity="center"
android:layout_margin="8dp"
android:background="#drawable/icon_img" />
#drawable/icon_img.xml:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/circle"/>
</layer-list>
#drawable/circle.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thicknessRatio="1.9"
android:useLevel="false" >
<solid android:color="#android:color/transparent" />
<stroke
android:width="10dp"
android:color="#android:color/white" />
</shape>
Why not using third party ?
Try this code
Bitmap picture = BitmapFactory.decodeResource(getResources(), R.mipmap.add_image);
ImageView imageView = (ImageView) findViewById(R.id.imgProfilePicture);
imageView.setImageBitmap(getRoundedBitmap(picture));
public Bitmap getRoundedBitmap(Bitmap bitmap){
Bitmap circleBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setShader(shader);
paint.setAntiAlias(true);
Canvas c = new Canvas(circleBitmap);
c.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint);
return circleBitmap;
}
Your xml file
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/imgProfilePicture"
android:layout_width="110dp"
android:layout_height="110dp"
android:layout_marginBottom="20dp"
app:civ_border_width="3dp"
app:civ_border_color="#color/light_gray" />
and add this in build.gradle
compile 'de.hdodenhof:circleimageview:2.1.0'
Cirular ImageView Done !
Do you want to use only code or you are ok with library too? If you are ok with library may I suggest using this library, helped me a lot. If you don't want to use library, you can use RoundedBitmapDrawable:
RoundedBitmapDrawable drawable =
RoundedBitmapDrawableFactory.create(context.getResources(), bitmap)
drawable.setCircular(true);
Use this drawable in your ImageView.
Major problem will be when you use Picasso to set image again to set to imageView view bounds not to the its background that you create.
If you programmatically set a one it will override your background!
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<shape android:shape="oval">
<solid android:color="#color/colorPrimary"/>
</shape>
</item>
</selector>
You can set this as background of your view.Then try to use view.setBackgroundResource(R.drawable.icon_img); . you will notice the change!
You can go through Add a background image to shape in xml Android
Mask ImageView with round corner background
to check the various ways people tried out here!
But with Picasso you can do this directly with out other 3rd parties.
final ImageView imageView = (ImageView) findViewById(R.id.group_icon_jsoup);
Picasso.with(YourActivity.this).load("http://i.imgur.com/DvpvklR.png")
.resize(100, 100)
.into(imageView, new Callback() {
#Override
public void onSuccess() {
Bitmap imageBitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
RoundedBitmapDrawable imageDrawable = RoundedBitmapDrawableFactory.create(getResources(), imageBitmap);
imageDrawable.setCircular(true);
imageDrawable.setCornerRadius(Math.max(imageBitmap.getWidth(), imageBitmap.getHeight()) / 2.0f);
imageView.setImageDrawable(imageDrawable);
}
#Override
public void onError() {
imageView.setImageResource(R.drawable.amanda);
}
});
Hello #Surjan here is the code which help to create a image in Any shape which you want only you need image of your choice shape with transparent and combination of any other color, following was the example :
protected Bitmap getPinnedImage(Bitmap original, int shapeImage) {
if (original == null) {
original = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_round_shape);
}
Bitmap mask = BitmapFactory.decodeResource(context.getResources(), shapeImage);
original = Bitmap.createScaledBitmap(original, mask.getWidth(), mask.getHeight(), true);
Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mCanvas.drawBitmap(original, 0, 0, null);
mCanvas.drawBitmap(mask, 0, 0, paint);
paint.setXfermode(null);
return result;
}
Here is the tow parameter first one is your original bitmap and second one is the your shape drawable, like following was the pin shape
now passing after this drawable you can get your image in pin shape no need to access any third party library.
Try this,
ImageView iv = (ImageView) addLinkDialog.findViewById(R.id.group_icon_jsoup);
Picasso.with(getBaseContext()).load(GroupImageUrl).transform(new RoundedTransformation(5,15, Color.parseColor("#27a3cb"))).fit().into(iv);
public class RoundedTransformation implements Transformation {
private int mBorderSize;
private int mCornerRadius = 0;
private int mColor;
public RoundedTransformation(int borderSize, int color) {
this.mBorderSize = borderSize;
this.mColor = color;
}
public RoundedTransformation(int borderSize, int cornerRadius, int color) {
this.mBorderSize = borderSize;
this.mCornerRadius = cornerRadius;
this.mColor = color;
}
#Override
public Bitmap transform(Bitmap source) {
int width = source.getWidth();
int height = source.getHeight();
Bitmap image = Bitmap.createBitmap(width, height, source.getConfig());
Canvas canvas = new Canvas(image);
canvas.drawARGB(0, 0, 0, 0);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Rect rect = new Rect(0, 0, width, height);
if(this.mCornerRadius == 0) {
canvas.drawRect(rect, paint);
}
else {
canvas.drawRoundRect(new RectF(rect),this.mCornerRadius, this.mCornerRadius, paint);
}
paint.setXfermode(new PorterDuffXfermode((PorterDuff.Mode.SRC_IN)));
canvas.drawBitmap(source, rect, rect, paint);
Bitmap output;
if(this.mBorderSize == 0) {
output = image;
}
else {
width = width + this.mBorderSize * 2;
height = height + this.mBorderSize * 2;
output = Bitmap.createBitmap(width, height, source.getConfig());
canvas.setBitmap(output);
canvas.drawARGB(0, 0, 0, 0);
rect = new Rect(0, 0, width, height);
paint.setXfermode(null);
paint.setColor(this.mColor);
paint.setStyle(Paint.Style.FILL);
canvas.drawRoundRect(new RectF(rect), this.mCornerRadius, this.mCornerRadius, paint);
canvas.drawBitmap(image, this.mBorderSize, this.mBorderSize, null);
}
if(source != output) source.recycle();
return output;
}
#Override
public String key() {
return "bitmapBorder(" +
"borderSize=" + this.mBorderSize + ", " +
"cornerRadius=" + this.mCornerRadius + ", " +
"color=" + this.mColor +")";
}
}
I'm trying to set a marker's color to colorAccent but somehow it doesn't work with this code:
Drawable drawable = getResources().getDrawable(R.drawable.ic_place_white_24dp);
drawable.setColorFilter(getResources().getColor(R.color.colorAccent), PorterDuff.Mode.MULTIPLY);
BitmapDescriptor bitmap = BitmapDescriptorFactory.fromBitmap(((BitmapDrawable) drawable).getBitmap());
Bitmap workingBitmap = Bitmap.createBitmap(((BitmapDrawable) drawable).getBitmap());
Bitmap mutableBitmap = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(mutableBitmap);
drawable.draw(canvas);
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(mutableBitmap);
markerOptions.icon(bitmapDescriptor);
I tried to switch the drawable from a plain white icon to a black one and also tried to switch from Mode.MULTIPLY to Mode.ADD. Both without success.
TRY THIS!!!!
private static Paint markerPaint;
private static Paint whitePaint;
Bitmap markerBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.mapmarker);
Bitmap resultBitmap = Bitmap.createBitmap(markerBitmap, 0, 0, markerBitmap.getWidth() - 1, markerBitmap.getHeight() - 1);
ColorFilter filter = new PorterDuffColorFilter(Themer.getPrimaryColor(getActivity()), PorterDuff.Mode.SRC_IN);
if (markerPaint == null) {
markerPaint = new Paint();
markerPaint.setColorFilter(filter);
} else {
markerPaint.setColorFilter(filter);
}
Canvas canvas = new Canvas(resultBitmap);
canvas.drawBitmap(resultBitmap, 0, 0, markerPaint);
if (Themer.shouldShowStopCounts(getActivity())) {
if (whitePaint == null) {
whitePaint = new Paint();
whitePaint.setColor(Color.WHITE);
whitePaint.setTextSize(40f);
whitePaint.setTextAlign(Paint.Align.CENTER);
}
canvas.drawText(item.name, resultBitmap.getWidth() / 2, resultBitmap.getHeight() / 2, whitePaint);
}
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(resultBitmap));
I have implemented the Switch Widget this way:
<android.support.v7.widget.SwitchCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textOff="#string/switch_on"
android:textOn="#string/switch_on"
app:showText="true"
android:gravity="right"
android:thumb="#drawable/slider_thumb"
app:switchMinWidth="200dp"
app:track="#drawable/slider_tracker">
Everything works fine, except that the text is written on top on the thumb. What i want t achieve is having the text displayed on the track. So, assuming the switch is checked, the text would be displayed on the left and when not checked, the textOff would be displayed on the right.
.
How can i achieve this. Thanks
I figured out i can achieve this by drawing a text on a bitmap, generate a bitmap drawable from that and change the track drawable of the switch to the bitmapdrawable.
Basically, i achieve this with the snippet below.
BitmapDrawable bitmapDrawable = new BitmapDrawable(drawTextToBitmap(this, R.drawable.test_, "Slide to Sign In"));
switchCompat.setTrackDrawable(bitmapDrawable);
public Bitmap drawTextToBitmap(Context gContext,
int gResId,
String gText) {
Resources resources = gContext.getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap bitmap =
BitmapFactory.decodeResource(resources, gResId);
android.graphics.Bitmap.Config bitmapConfig =
bitmap.getConfig();
// set default bitmap config if none
if (bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
// resource bitmaps are imutable,
// so we need to convert it to mutable one
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
// new antialised Paint
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// text color - #3D3D3D
paint.setColor(Color.rgb(61, 61, 61));
// text size in pixels
paint.setTextSize((int) (10 * scale));
// text shadow
paint.setShadowLayer(1f, 0f, 1f, Color.WHITE);
// draw text to the Canvas center
Rect bounds = new Rect();
paint.getTextBounds(gText, 0, gText.length(), bounds);
int x = (bitmap.getWidth() - (170));
int y = (bitmap.getHeight() + bounds.height()) / 2;
canvas.drawText(gText, x, y, paint);
return bitmap;
}
As for changing the drawable when the the switch is on and off,you can play with that using
switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
}
});
I am using the CommonsWare CWAC-Camera library (https://github.com/commonsguy/cwac-camera) to wrap the native Android Camera API.
I would like to allow the user to select a point on the preview image before taking a picture, then (accurately) pick out that same point on the final image after they have taken the picture. While this works approximately, the markup on the final image is typically off-target by about 100-200 pixels.
To start with, I am capturing the user's original selected point by setting an OnTouchListener on the CameraView. I am then storing the X and Y coordinates from the MotionEvent. Just to help with visual verification, I am also immediately drawing a circle at the coordinates the user selected, before they take the picture.
When the user takes the picture, I have subclassed from SimpleCameraHost to override saveImage, in order to draw a corresponding circle on the final image before it is written to storage. In order to calculate where to draw the circle on the final image, I am doing the following:
Create a Bitmap the same size and shape as the TextureView that was used to draw the preview
Draw a circle on that Bitmap at the same coordinates as was drawn on-screen
Scale the markup-Bitmap up to the final image size (using Matrix.ScaleToFit.Center) and overlay it on top of the actual final photo image
This is not sufficiently accurate, however - at least, not on the Nexus 7 (2013) that I am testing with. I am not sure what I am missing in the placement calculations for adding the markup to the final image.
A simplified example to demonstrate the problem follows:
MainActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCameraContainer = findViewById(R.id.camera_container);
mCanvasView = (CanvasView)findViewById(R.id.canvas_view);
FragmentManager fmgr = getFragmentManager();
FragmentTransaction ft = fmgr.beginTransaction();
mCameraFragment = (CameraFragment)fmgr.findFragmentByTag(CAMERA_FRAGMENT_TAG);
if (null == mCameraFragment) {
mCameraFragment = new CameraFragment();
ft.add(R.id.camera_container, mCameraFragment, CAMERA_FRAGMENT_TAG);
}
ft.commit();
if (null == mCameraHost) {
mCameraHost = new MyCameraHost(this);
}
mCameraFragment.setHost(mCameraHost);
ViewTreeObserver ccObserver = mCameraContainer.getViewTreeObserver();
ccObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
CameraView cv = (CameraView)mCameraFragment.getView();
View previewWidget = ((ViewGroup)cv).getChildAt(0);
mCameraHost.setPreviewSize(previewWidget.getWidth(), previewWidget.getHeight());
cv.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent e) {
mCanvasView.setPoint(e.getX(), e.getY());
mCameraHost.setPoint(e.getX(), e.getY());
return true;
}
});
mCameraContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
Button photoButton = (Button)findViewById(R.id.takePhotoButton);
photoButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mCameraFragment.takePicture();
}
});
}
MyCameraHost.java:
#Override
public void saveImage(PictureTransaction xact, byte[] image) {
// decode the final image as a Bitmap
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inMutable = true;
Bitmap imageBitmap = BitmapFactory.decodeByteArray(image, 0, image.length, opt);
// draw a blank Bitmap with just the markup, using a canvas size equivalent to the preview view
Bitmap markerBitmap = Bitmap.createBitmap(previewViewWidth, previewViewHeight, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(markerBitmap);
Paint p = new Paint();
p.setStrokeWidth(10);
p.setStyle(Style.FILL);
p.setColor(Color.BLUE);
c.drawCircle(previewMarkerX, previewMarkerY, 20, p);
// scale the markup bitmap up to final-image size using Matrix.ScaleToFit.CENTER
Matrix m = new Matrix();
m.setRectToRect(new RectF(0, 0, previewViewWidth, previewViewHeight), new RectF(0, 0, imageBitmap.getWidth(), imageBitmap.getHeight()), Matrix.ScaleToFit.CENTER);
// overlay the scaled marker Bitmap onto the image
Canvas imageCanvas = new Canvas(imageBitmap);
imageCanvas.drawBitmap(markerBitmap, m, null);
// save the combined image
ByteArrayOutputStream bos = new ByteArrayOutputStream();
imageBitmap.compress(CompressFormat.JPEG, 70, bos);
byte[] image2 = bos.toByteArray();
super.saveImage(xact, image2);
}
layout XML:
<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"
tools:context=".MainActivity" >
<FrameLayout
android:id="#+id/camera_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.example.cwaccameratouchpoint.CanvasView
android:id="#+id/canvas_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#id/camera_container"
android:layout_alignRight="#id/camera_container"
android:layout_alignTop="#id/camera_container"
android:layout_alignBottom="#id/camera_container" />
<Button
android:id="#+id/takePhotoButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:text="go" />
</RelativeLayout>
As per comments from CommonsWare, I updated saveImage below to include the full-bleed offset and to spell out the transform calculations. It is an improvement, but still not as accurate as it should be:
// decode the final image as a Bitmap
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inMutable = true;
Bitmap imageBitmap = BitmapFactory.decodeByteArray(image, 0, image.length, opt);
int finalImageWidth = imageBitmap.getWidth();
int finalImageHeight = imageBitmap.getHeight();
// calculate selected point x and y values as applied to full-size final image
// apply full-bleed-based offset, where xoffset and yoffset represent the
// offset of the TextureView within its parent CameraView
int bleedAdjustedX = (int)previewMarkerX - xoffset;
int bleedAdjustedY = (int)previewMarkerY - yoffset;
// calculate offset for change in aspect ratio
// for now, assume portrait orientation only
double finalImageAspectRatio = (double)finalImageHeight / (double)finalImageWidth;
double aspectAdjustedWidth = (double)previewViewHeight / finalImageAspectRatio;
double aspectXOffset = (aspectAdjustedWidth - previewViewWidth) / 2;
int aspectAdjustedX = bleedAdjustedX + (int)aspectXOffset;
// scale adjusted coordinates for full-size image
double normalizedAdjustedX = (double)aspectAdjustedX / aspectAdjustedWidth;
double normalizedAdjustedY = (double)bleedAdjustedY / (double)previewViewHeight;
double scaledX = normalizedAdjustedX * (double)finalImageWidth;
double scaledY = normalizedAdjustedY * (double)finalImageHeight;
// draw markup on final image
Canvas c = new Canvas(imageBitmap);
Paint p = new Paint();
p.setStrokeWidth(10);
p.setStyle(Style.FILL);
p.setColor(Color.BLUE);
c.drawCircle((float)scaledX, (float)scaledY, 20, p);
// save marked-up image
ByteArrayOutputStream bos = new ByteArrayOutputStream();
imageBitmap.compress(CompressFormat.JPEG, 70, bos);
byte[] image2 = bos.toByteArray();
super.saveImage(xact, image2);
Setting background doesn't seem to give any hint on size for android.
Hence I'm looking for a way to create an image with a specific color.
(would be better if could be done in xml)
in iOS this could be achieved by
+ (UIImage*)placeHolderImage
{
static UIImage* image = nil;
if(image != nil)
return image;
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
// Seashell color
UIColor* color = [UIColor colorWithRed:255/255.0 green:245/255.0 blue:238/255.0 alpha:1.0];
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Here is the equivalent Android code:
// CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
Rect rect = new Rect(0, 0, 1, 1);
//UIGraphicsBeginImageContext(rect.size);
//CGContextRef context = UIGraphicsGetCurrentContext();
Bitmap image = Bitmap.createBitmap(rect.width(), rect.height(), Config.ARGB_8888);
Canvas canvas = new Canvas(image);
//UIColor* color = [UIColor colorWithRed:255/255.0 green:245/255.0 blue:238/255.0 alpha:1.0];
int color = Color.argb(255, 255, 245, 238);
//CGContextSetFillColorWithColor(context, [color CGColor]);
Paint paint = new Paint();
paint.setColor(color);
//CGContextFillRect(context, rect);
canvas.drawRect(rect, paint);
//image = UIGraphicsGetImageFromCurrentImageContext();
//UIGraphicsEndImageContext();
/** nothing to do here, we already have our image **/
/** and the canvas will be released by the GC **/
Now, if you want to do this in XML its much easier:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<size android:width="1px" android:height="1dp"/>
<solid android:color="#FFFFF5EE/>
</shape>
Although that won't give you a Bitmap, but a Drawable. It's just fine if you intend to just draw it somewhere. If you actually need a Bitmap, then you will have to use the above code to create a Canvas from a Bitmap and draw your Drawable into it.
This helps you in creating a bitmap image with a specific color.
firstly create a bitmap with name sampleBitmap like below
Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
Bitmap sampleBitmap = Bitmap.createBitmap(300, 300, conf); // this creates a MUTABLE bitmap
next use the following code to get each pixel of the created bitmap
// int[] pixels = new int[sampleBitmap.getHeight()*sampleBitmap.getWidth()];
for (int i=0; i < sampleBitmap.getWidth(); i++)
{
for (int j=0; j < sampleBitmap.getHeight(); i++)
{
sampleBitmap.setPixel(i, j, Color.rgb(someColor1, someColor2, someColor3));
}
}
using this you can set the bitmap to the listview item so that the listitem doesnt collapse