Ok so first of I will take you through the basics of my App. So far you take picture using the camera which then gets saved into a folder. Once the picture has been took a new Activity opens and shows the picture on screen in a ImageView.
The effect I am trying to achive is something along the lines of being able to create png layers over the top of the picture in the ImageView with the onClick Event. So say I have 5 transparent png's I want to have five onClick events which with each touch of the screen a new png image will get displayed over the top of the picture in the ImageView so it would take 5 onClick (touch of screen) to show all the transparent png's over the top of the picture.
I think I am nearly there with the code below but I think I need to create an array of the images in the drawable folder that need to be displayed with each onClick event, I think the array should be nextBitmap but not to sure.
Update Sparkys answer
I have tried adding private Integer[] nextBitmap = { R.drawable.img1, R.drawable.img2 }; but I am getting the error The method getBitmapOverlay(Bitmap, Bitmap, int, int) in the type BeatEmUp is not applicable for the arguments (Bitmap, Integer[], int, int) anyone know what this could be do I need to add the private Integer[]...... outside the onCreate method?
public class Image extends Activity {
Bitmap myBitmap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.Image);
String myRef = this.getIntent().getStringExtra("filepath");
File imgFile = new File(myRef);
Log.e("No ref", myRef);
if(imgFile.exists()) {
final Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
final ImageView myImage = (ImageView) findViewById(R.id.beatemup);
myImage.setImageBitmap(myBitmap);
myImage.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
myBitmap = getBitmapOverlay(myBitmap, nextBitmap, 0, 0);
myImage.setImageBitmap(myBitmap);
}
});
}
}
public static Bitmap getBitmapOverlay(Bitmap bmp1, Bitmap bmp2, int left, int top) {
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, 0, 0, null);
canvas.drawBitmap(bmp2, left, top, null);
return bmOverlay;
}
}
Ok, I have made you a small working sample that might be what you are looking for.
I break my own rules here because I did code for you. As I know that you are a beginner, you should definitively understand the following code before you use it.
public class Image extends Activity {
Bitmap myBitmap;
Integer[] mBitmapIds = new Integer[] { R.drawable.ic_launcher, R.drawable.ic_launcher };
Random mRand = new Random();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
final ImageView myImage = (ImageView) findViewById(R.id.imageview);
myImage.setImageBitmap(myBitmap);
myImage.setOnClickListener(new OnClickListener() {
int i = 0;
public void onClick(View v) {
if (i >= mBitmapIds.length) {
i = 0;
}
myImage.setImageBitmap(getBitmapOverlay(myBitmap, BitmapFactory.decodeResource(getResources(), mBitmapIds[i]), 0, 0));
}
});
}
public Bitmap getBitmapOverlay(Bitmap bmp1, Bitmap bmp2, int left, int top) {
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(),
bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, 0, 0, null);
left += mRand.nextInt(20);
top += mRand.nextInt(20);
canvas.drawBitmap(bmp2, left, top, null);
return bmOverlay;
}
}
See the Hello, Views tutorial, GridView chapter for an example of an array of references to Drawables.
Related
I want to implement a drag-and-drop functionality within a recyclerview. Everything goes perfectly until I want to customize the looks of the view being dragged (not the view from which the drag event starts, I want to modify the "shadow" and keep the original view the same).
I've tried to make a bitmap out of the view being passed, but the end result is both the original item and the Shadow are modified AND the original view loses its position on the list... WTF
Here is my code:
public class ImageDragShadowBuilder extends View.DragShadowBuilder {
private Bitmap shadow;
LinearLayout linearLayout;
private ImageDragShadowBuilder() {
super();
}
public static ImageDragShadowBuilder create(Context context, View view) {
ImageDragShadowBuilder builder = new ImageDragShadowBuilder();
builder.linearLayout = (LinearLayout) view.findViewById(R.id.metric_item);
builder.linearLayout.setBackgroundResource(R.drawable.background_item_dragging);
builder.shadow = createBitmapFromView(builder.linearLayout);
return builder;
}
public View getLayout() {
return linearLayout;
}
private static Bitmap createBitmapFromView(View v) {
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
v.layout(0, 0, v.getWidth(), v.getHeight());
v.draw(new Canvas(b));
return b;
}
#Override
public void onDrawShadow(Canvas canvas) {
canvas.drawBitmap(shadow, 0, 0, null);
}
#Override
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
shadowSize.x = shadow.getWidth();
shadowSize.y = shadow.getHeight();
shadowTouchPoint.x = shadowSize.x / 2;
shadowTouchPoint.y = shadowSize.y / 2;
}
}
Any ideas?
I think that there are 2 problems :
Setting the background on the view attached to the RecyclerView affects the original item and the shadow
Triggering a layout changes the item's children position
Basically you can use the original view, but you should never modify it. A slightly modified version of your shadow builder could be :
public static ImageDragShadowBuilder create(Context context, View view) {
ImageDragShadowBuilder builder = new ImageDragShadowBuilder();
builder.linearLayout = (LinearLayout) view.findViewById(R.id.metric_item);
// do not change the original view
// we will draw the background directly later
// builder.linearLayout.setBackgroundResource(R.drawable.background_item_dragging);
builder.shadow = createBitmapFromView(builder.linearLayout);
return builder;
}
private static Bitmap createBitmapFromView(View v) {
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
// do not change the original view
// v.layout(0, 0, v.getWidth(), v.getHeight());
Canvas c = new Canvas(b);
// draw the background
Drawable background = v.getContext().getDrawable(R.drawable.background_item_dragging);
background.setBounds(0, 0, b.getWidth(), b.getHeight());
background.draw(c);
v.draw(c);
return b;
}
I am getting bitmap of gridview using this line of code
aftershu = Bitmap.createBitmap(image_grid.getDrawingCache());
But when i get this i'm not getting the current view of gridview i'm getting one view before the current view .
Here is my code
image_grid.setDrawingCacheEnabled(true);
image_grid.buildDrawingCache(true);
// Bitmap b = Bitmap.createBitmap(mGridView.getDrawingCache());
beforeshu= Bitmap.createBitmap(image_grid.getDrawingCache());
Bitmap x=getResizedBitmap(beforeshu,200,200);
b1.setImageBitmap(x);
Collections.shuffle(smallimages);
image_grid.setAdapter(new SmallImageAdapter(this, smallimages));
// image_grid.setAdapter(new SmallImageAdapter());
image_grid.setNumColumns((int) Math.sqrt(smallimages.size()));
image_grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
int firstclick;
int counter=0;
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
counter++;
if (counter % 2 == 0) {
firstclick = position;
Bitmap data1 = smallimages.get(position);
} else {
Bitmap swapImage = smallimages.get(position);
smallimages.set(position, smallimages.get(firstclick));
smallimages.set(firstclick, swapImage);
image_grid.invalidateViews();
}
aftershu = Bitmap.createBitmap(image_grid.getDrawingCache());
}
});
this beforeshu is getting correct bitmap of before shuffling but aftershu bitmap is returning the image view before last swap in grid view
I inserted this line after the onclick i.e when clicking the checkresult but it returns always the beforeshu bitmap.
my output left image is before shuffle right image is the bitmap i get when i click checkresult
So how to get the bitmap of current view of gridview i.e.when i click checkresult button
I solved by this method from stackoverflow
public static Bitmap getBitmapFromView(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable!=null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
view.draw(canvas);
return bitmap;
}
i passed gridview to this method and got the current bitmap
I would like to show the custom marker to google map and cluster them. The marker contains a ImageView that will shows the avatar that is downloaded from network. Here is my target:
Everythings are OK, however, when I implemented the Google Maps Android Marker Clustering Utility, the ImageView shows the same avatar (sometime two wrong avatars).
Here is my custom MarkerRender:
public class MarkerRender extends DefaultClusterRenderer<Image> {
private static final String TAG = MarkerRender.class.getSimpleName();
private IconGenerator clusterGenerator;
private IconGenerator markerGenerator;
private ImageView mImgMarkerThumbnail;
private ImageView mImgMarkerClusterThumbnail;
private TextView txtSizeCluster;
private Activity activity;
private Bitmap mask, background;
private AtomicInteger imageDownloadCounter;
private int totalItem;
private ImageSize imageSize;
public MarkerRender(FragmentActivity activity, GoogleMap mMap, ClusterManager<Image> mClusterManager) {
super(activity, mMap, mClusterManager);
this.activity = activity;
imageDownloadCounter = new AtomicInteger(0);
mask = BitmapFactory.decodeResource(activity.getResources(),
R.drawable.annotation_behind);
background = BitmapFactory.decodeResource(activity.getResources(),
R.drawable.annotation_behind);
setUpClusterIcon();
setUpMarker();
}
private void setUpClusterIcon() {
clusterGenerator = new IconGenerator(activity);
View clusterView = activity.getLayoutInflater().inflate(R.layout.custom_marker_cluster, null);
txtSizeCluster = (TextView) clusterView.findViewById(R.id.tv_number_marker);
mImgMarkerClusterThumbnail = (ImageView) clusterView.findViewById(R.id.img_load);
clusterGenerator.setContentView(clusterView);
clusterGenerator.setBackground(null);
}
private void setUpMarker() {
markerGenerator = new IconGenerator(activity);
View markerView = activity.getLayoutInflater().inflate(R.layout.custom_marker, null);
mImgMarkerThumbnail = (ImageView) markerView.findViewById(R.id.img_load);
markerGenerator.setContentView(markerView);
markerGenerator.setBackground(null);
}
#Override
protected void onBeforeClusterItemRendered(final Image image, final MarkerOptions markerOptions) {
initImageSizeIfNeed();
Bitmap icon = markerGenerator.makeIcon();
PFLogManager.INSTANCE.logE(TAG, "maken icon: " + icon.hashCode());
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
icon.recycle();
}
#Override
protected void onClusterItemRendered(final Image image, Marker marker) {
super.onClusterItemRendered(image, marker);
ImageLoader.getInstance().loadImage(image.getMapImageLink(), imageSize,
new SimpleImageLoadingListener() {
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
Bitmap croppedBitmap = Helpers.makeCroppedBitmap(loadedImage, background, mask);
mImgMarkerThumbnail.setImageBitmap(croppedBitmap);
}
});
}
#Override
protected void onBeforeClusterRendered(Cluster<Image> cluster, MarkerOptions markerOptions) {
initImageSizeIfNeed();
Bitmap icon = clusterGenerator.makeIcon();
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
icon.recycle();
}
#Override
protected void onClusterRendered(Cluster<Image> cluster, Marker marker) {
super.onClusterRendered(cluster, marker);
ArrayList<Image> list = new ArrayList<>(cluster.getItems());
setTextNumberMarker(cluster);
String urlFirstImage = list.get(0).getMapImageLink();
ImageLoader.getInstance().loadImage(urlFirstImage, imageSize,
new SimpleImageLoadingListener() {
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
final Bitmap croppedBitmap = Helpers.makeCroppedBitmap(loadedImage, background, mask);
mImgMarkerClusterThumbnail.setImageBitmap(croppedBitmap);
}
});
}
private void loadClusterThumbnail(String url) {
}
private void setTextNumberMarker(Cluster<Image> cluster) {
int size = cluster.getSize();
if (size > 99) {
txtSizeCluster.setText("99+");
} else {
txtSizeCluster.setText(String.valueOf(cluster.getSize()));
}
}
#Override
protected boolean shouldRenderAsCluster(Cluster cluster) {
return cluster.getSize() > 1;
}
}
I've guess that the issue is I use only one ImageView to show those avatar, so I try to use unique ImageView for each marker (by inflat new one from xml every time needed), but the result is they are all show the blank marker (just the background and there is no avatar).
I've resolved it myself. My solution is use the Marker.setIcon() method after the image is downloaded from netword or got from cache. I dont use the ImageView anymore.
So, i modified the above MarkerRender class:
The setUpClusterIcon() method:
private void setUpClusterIcon() {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(markerWidth, markerHeight);
ImageView marker = new ImageView(activity);
marker.setLayoutParams(params);
clusterGenerator = new IconGenerator(activity);
clusterGenerator.setContentView(marker);
clusterGenerator.setBackground(null);
}
And the onClusterItemRendered() method:
protected void onClusterItemRendered(final Image image, final Marker marker) {
super.onClusterItemRendered(image, marker);
ImageLoader.getInstance().loadImage(image.getMapImageLink(), imageSize,
new SimpleImageLoadingListener() {
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
Bitmap croppedBitmap = Helpers.makeClusterItemBitmap(background, loadedImage, mask);
try {
marker.setIcon(BitmapDescriptorFactory.fromBitmap(croppedBitmap));
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
Also the makeClusterItemBitmap helper method:
public static Bitmap makeClusterItemBitmap(Bitmap background, Bitmap original, Bitmap mask) {
Bitmap croppedOriginal = makeCroppedBitmap(original, mask);
Bitmap result = Bitmap.createBitmap(background.getWidth(), background.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(result);
croppedOriginal = Bitmap.createScaledBitmap(croppedOriginal, croppedOriginal.getWidth() - 20, croppedOriginal.getHeight() - 20, true);
mCanvas.drawBitmap(background, 0, 0, null);
mCanvas.drawBitmap(croppedOriginal, 10, 10, null);
return result;
}
public static Bitmap makeCroppedBitmap(Bitmap original, Bitmap mask) {
original = Bitmap.createScaledBitmap(original, mask.getWidth(),
mask.getHeight(), true);
Bitmap result = Bitmap.createBitmap(original.getWidth(), original.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;
}
Done, finish three nightmare researchingdays days :P
However, this approach leads new issue: the performance. Cause by drawing new bitmap with many layers, the map is laggy a bit. I'm thinking in improving this :)
Any sugguestion are appriciate :D
I want to take screenshot of an activity and show it in next activity on button click.
I'm using following code but its not working.
Please let me know if anyone knows the answer:
choose.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mainlayout.setDrawingCacheEnabled(true);
mainlayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
mainlayout.layout(0, 0, mainlayout.getMeasuredWidth(), mainlayout.getMeasuredHeight());
mainlayout.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(mainlayout.getDrawingCache());
mainlayout.setDrawingCacheEnabled(false); // clear drawing cache
Intent i4=new Intent(Screen3.this,Screen4.class);
i4.putExtra("BitmapImage", b);
startActivity(i4);
}//onclick
});
public static Bitmap captureScreen(View v){
Bitmap bitmap = null;
try {
if(v!=null)
{
int width = v.getWidth();
int height = v.getHeight();
Bitmap screenshot = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
v.draw(new Canvas(screenshot));
}
}
catch (Exception e){
Log.d("captureScreen", "Failed");
}
return bitmap;
}
v is the what is being capturing (any layout)
I'm trying to follow instructions from Android developers site but I must be doing something wrong.
I tried to create custom ImageView and draw 2 bitmaps onto it.
Activity
public class TestActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
LinearLayout left = (LinearLayout) findViewById(R.id.container);
ModuleImageView iv = new ModuleImageView(this);
left.addView(iv);
iv.invalidate();
}
}
ImageView
public class ModuleImageView extends ImageView{
public ModuleImageView(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
Bitmap b1 = BitmapFactory.decodeResource(getResources(), R.drawable.main_engine);
Bitmap b2 = BitmapFactory.decodeResource(getResources(), R.drawable.energy);
canvas.drawBitmap(b1, 0, 0, null);
canvas.drawBitmap(b2, 5, 5, null);
super.onDraw(canvas);
}
}
There is nothing showing up on the screen and it's probably because the onDraw method is never executed.
Use LayerDrawable instead. Construct it and pass to a normal ImageView