How to place ImageButton at x, y location? - android

I want to place ImageButton at x, y location of my view.
The problem is that Android adds padding around image.
Because I don't know exact size of padding, I cannot place image button at exact location.
So, I want to remove padding.
How can I remove padding around image programmatically?
button.setPadding(0, 0, 0, 0) makes button width shorter and height longer than bitmap.
button.getLayoutParams().width gives minus value.
What I tried so far is like this.
protected class MyLayout extends RelativeLayout {
Bitmap img;
ImageButton button;
public MyLayout(Context context) {
button = new ImageButton(context);
img = BitmapFactory.decodeResource(getResources(), R.drawable.img);
button.setImageBitmap(img);
params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
button.setLayoutParams(params);
params.setMargins(x, y, 0, 0);
button.setBackgroundDrawable(null);
addView(button, params);
}
}

EDIT
Use this...
MarginLayoutParams marginParams = new MarginLayoutParams(image.getLayoutParams());
int left = someValue;
int top = someValue;
marginParams.setMargins(left, top, 0, 0);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
image.setLayoutParams(layoutParams);

Related

RelativeLayout align parent bottom does not align at bottom

I have a custom circular layout using a relative layout:
public class CircularLayout extends RelativeLayout implements OnDragListener {
private DropCallback onDrop = null;
private ImageButton imageButton = null;
private ImageView imageViewBackgroundWave = null;
private int radius = -1;
private double step = -1;
private double angle = -1;
private static final int CENTER_ID = 111;
public CircularLayout(Context context, DropCallback onDrop, int radius, List<View> views) {
super(context);
this.onDrop = onDrop;
this.radius = radius;
this.step = (2 * Math.PI) / views.size();
this.initView(context, views);
}
private void initView(Context context, List<View> views) {
RelativeLayout.LayoutParams layoutParamsView = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
this.setLayoutParams(layoutParamsView);
RelativeLayout.LayoutParams layoutParamsImageview = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParamsImageview.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
layoutParamsImageview.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
this.imageViewBackgroundWave = new ImageView(this.getContext());
this.imageViewBackgroundWave.setLayoutParams(layoutParamsImageview);
this.imageViewBackgroundWave.setImageDrawable(this.getResources().getDrawable(R.drawable.background_wave));
this.addView(this.imageViewBackgroundWave);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
this.imageButton = new ImageButton(context);
this.imageButton.setId(CENTER_ID);
this.imageButton.setLayoutParams(layoutParams);
this.imageButton.setImageResource(R.drawable.ic_power_on);
this.imageButton.getBackground().setAlpha(0);
this.imageButton.setOnDragListener(this);
this.addView(this.imageButton);
for(View view : views) {
this.addView(this.placeView(view));
}
}
private View placeView(View view) {
view.measure(0, 0);
this.imageButton.measure(0, 0);
int x = (int)((view.getMeasuredWidth() / 2) + this.radius * Math.cos(this.angle));
int y = (int)((view.getMeasuredHeight() / 2) + this.radius * Math.sin(this.angle));
this.angle += this.step;
int deltaX = view.getMeasuredWidth();
int deltaY = view.getMeasuredHeight();
int deltaImageX = this.imageButton.getMeasuredWidth() / 2;
int deltaImageY = this.imageButton.getMeasuredHeight() / 2;
int xToDraw = ((x - deltaX) - deltaImageX);
int yToDraw = ((y - deltaY) - deltaImageY);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.ABOVE, CENTER_ID);
layoutParams.addRule(RelativeLayout.RIGHT_OF, CENTER_ID);
layoutParams.setMargins(xToDraw, 0, 0, yToDraw);
view.setLayoutParams(layoutParams);
return view;
}
#Override
public boolean onDrag(View view, DragEvent event) {
return this.onDrop.onDrop(view, event);
}
}
Unfortunately the imageview (imageViewBackgroundWave) is not aligning at the bottom. It aligns a little bit higher:
So the question is: how can I align my imageview to the bottom of the screen?
The image is exactly as high and as wide as the blue stripe. there is no
padding or white color in it. Its just the blue stripe shown in the picture above.
EDIT:
The background_wave.png:
I use this custom layout in my MenuFragment and call it with the following code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// ... init the imagebuttons in the list of views
this.circleView = new CircularLayout(this.getActivity(), this, 250, views);
this.circleView.setOnDragListener(this);
this.circleView.setBackground(this.getResources().getDrawable(R.drawable.background));
return this.circleView;
}
You can get the ImageView to stick to the bottom by adding this line of code:
imageView.setScaleType(ScaleType.FIT_END);
The reason for the weirdness is that the ImageView bounds are calculated by the layout engine first, then the image inside the ImageView is scaled to fit the allocated area according to the scale type.
Using WRAP_CONTENT for the ImageView allocates an area based on the size of the unscaled image bitmap - even if it is larger than the screen. Your background_wave.png file is wider than the screen, so a larger area than is needed is allocated. Then afterwards when the image gets fitted inside the layout area using FIT_CENTER it gets shrunk down and centered, so you end up up with white space above and below it.
You can verify this by resizing your background_wave.png to be 1/4 the size: it should align the bottom even without the above code change.
You are setting width and height twice with RelativeLayout.LayoutParams.WRAP_CONTENT and RelativeLayout.ALIGN_PARENT_BOTTOM
Try this:
private void initView(Context context) {
RelativeLayout.LayoutParams layoutParamsView = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
this.setLayoutParams(layoutParamsView);
RelativeLayout.LayoutParams layoutParamsImageview = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
this.imageView = new ImageView(this.getContext());
this.imageView.setLayoutParams(layoutParamsImageview);
this.imageView.setImageDrawable(this.getResources().getDrawable(R.drawable.background_wave));
this.addView(this.imageView);
}
I also recommend you to use visual designer with XML to test layout's rules and parameters, then, if you need it, you can set that rules in code to get the same result.

Android negative margin does not work

I have encountered a problem when i try to give a negative left margin to a LinearLayout.
The negative margin does not appear.
Here is my code
HorizontalScrollView hview = new HorizontalScrollView(context); // HorizontalScrollView is the outer view
RelativeLayout.LayoutParams hs_lot_params = new RelativeLayout.LayoutParams(164, 164);
hs_lot_params.setMargins(100, 100, 0, 0); // set the positions
ImageView image = new ImageView(context);
image.setBackgroundResource(R.drawable.leder);
LinearLayout.LayoutParams img_lot_params = new LinearLayout.LayoutParams(164, 164);
img_lot_params.setMargins(0, 0, 0, 0);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(164, 164);
layoutParams.setMargins(-132, 0, 0, 0);
ll.addView(image, img_lot_params);
hview.addView(ll, layoutParams);
Note: my plan is to scroll the image from left to right.
First, the left part of the image is hidden and can scroll to right to see the full image
ViewGroup.MarginLayoutParams params =
(ViewGroup.MarginLayoutParams)view.getLayoutParams(); params.topMargin = -100;
Negative margins should work in LinearLayout and RelativeLayout. What you probably need, is to scroll the HorizontalScrollView with scrollBy(int x, int y) or scrollTo(int x, int y) to achieve the "peek and scroll" effect you described.
Also keep in mind that using raw pixel units is generally a bad idea as the actual size will depend on the pixel density of the screen. Prefer dp measurements instead.

Custom Rotating of an image view

imageView.SetRotation(theta) centerize the view around the pivot point and rotates the image around this pivot by theta degrees, thats nice, but how can i rotate an image view without first centerizing it around this pivot?
to clearify my question, imagine a board and an image on it, what setRotation does is sticking a pin in the middle of this image and rotate it then, what i want is to pick a pivot - say image's bottom left stick a pin there and then rotate it.
hopefully my question is clear, and solveable!
thanks!
You can set a new pivot point using:
setPivotY(float pivotY);
setPivotX(float pivotX);
After that, the rotation will be made using the new pivot point set by the above methods.
--EDITED--
I used this method to add a ImageView to my layout.
private ImageView addImageView(RelativeLayout mainLayout, int x, int y, int width, int height, OnClickListener onClickListener){
ImageView imageView = new ImageView(this);
imageView.setAdjustViewBounds(false);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.height = height;
params.width = width;
imageView.setLayoutParams(params);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setImageDrawable(getResources().getDrawable(R.drawable.marker_red));
params.leftMargin = x - width/2;
params.topMargin = y - height/2;
imageView.setOnClickListener(onClickListener);
mainLayout.addView(imageView);
return imageView;
}
I called the method with this parameters:
ImageView imageView;
imageView = addImageView(mainLayout, 200, 300, 200, 200, new OnClickListener() {
#Override
public void onClick(View v) {
imageView.setPivotX(200);
imageView.setPivotY(200);
imageView.setRotation(45);
}
});
Finally, you just click on the image, and the image rotates 45 degrees.
regards

Design dynamic hotspot on Image in Android

I have to develop a UI like below:
I want to show this type of image and show hotspot on that image. The position of hotspot will be dynamic, as per x,y and radius provided the circle will be drawn on the original picture. The user can click on the hotspots and onclick action will be defined on the specific hotspot on which the user will click.
What is best process to develop this type of UI?
Make your main layout a RelativeLayout and then you can add programmatically a ImageView with an onClickListener to your layout with the following code:
private void addImageView(RelativeLayout mainLayout, int x, int y, int width, int height, OnClickListener onClickListener){
ImageView imageView = new ImageView(this);
imageView.setAdjustViewBounds(false);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.height = height;
params.width = width;
imageView.setLayoutParams(params);
imageView.setScaleType(ImageView.ScaleType.FIT_XY); //remove this if you want to keep aspect ratio
imageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher)); //here goes your drawable
params.leftMargin = x - width/2;
params.topMargin = y - height/2;
imageView.setOnClickListener(onClickListener);
mainLayout.addView(imageView);
}
to use it you call:
RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.relativeLayout); //this is your main layout
addImageButton(mainLayout, 200, 300, 200, 200, new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "clicked", Toast.LENGTH_SHORT).show();
}
});
You can also use a ImageButton to achive the same porpose, although the image size will be affected by button border:
private void addImageButton(RelativeLayout mainLayout, int x, int y, int width, int height, OnClickListener onClickListener){
ImageButton imageButton = new ImageButton(this);
imageButton.setAdjustViewBounds(true);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.height = height;
params.width = width;
imageButton.setLayoutParams(params);
imageButton.setScaleType(ImageView.ScaleType.FIT_XY);
imageButton.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher));
params.leftMargin = x - width/2;
params.topMargin = y - height/2;
imageButton.setOnClickListener(onClickListener);
mainLayout.addView(imageButton);
}
Try it.

How to set margin of ImageView using code, not xml

I want to add an unknown number of ImageView views to my layout with margin. In XML, I can use layout_margin like this:
<ImageView android:layout_margin="5dip" android:src="#drawable/image" />
There is ImageView.setPadding(), but no ImageView.setMargin(). I think it's along the lines of ImageView.setLayoutParams(LayoutParams), but not sure what to feed into that.
Does anyone know?
android.view.ViewGroup.MarginLayoutParams has a method setMargins(left, top, right, bottom). Direct subclasses are: FrameLayout.LayoutParams, LinearLayout.LayoutParams and RelativeLayout.LayoutParams.
Using e.g. LinearLayout:
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(left, top, right, bottom);
imageView.setLayoutParams(lp);
MarginLayoutParams
This sets the margins in pixels. To scale it use
context.getResources().getDisplayMetrics().density
DisplayMetrics
image = (ImageView) findViewById(R.id.imageID);
MarginLayoutParams marginParams = new MarginLayoutParams(image.getLayoutParams());
marginParams.setMargins(left_margin, top_margin, right_margin, bottom_margin);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
image.setLayoutParams(layoutParams);
All the above examples will actually REPLACE any params already present for the View, which may not be desired. The below code will just extend the existing params, without replacing them:
ImageView myImage = (ImageView) findViewById(R.id.image_view);
MarginLayoutParams marginParams = (MarginLayoutParams) image.getLayoutParams();
marginParams.setMargins(left, top, right, bottom);
Kevin's code creates redundant MarginLayoutParams object. Simpler version:
ImageView image = (ImageView) findViewById(R.id.main_image);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(image.getLayoutParams());
lp.setMargins(50, 100, 0, 0);
image.setLayoutParams(lp);
If you want to change imageview margin but leave all other margins intact.
Get MarginLayoutParameters of your image view in this case: myImageView
MarginLayoutParams marginParams = (MarginLayoutParams) myImageView.getLayoutParams();
Now just change the margin you want to change but leave the others as they are:
marginParams.setMargins(marginParams.leftMargin,
marginParams.topMargin,
150, //notice only changing right margin
marginParams.bottomMargin);
I use simply this and works great:
ImageView imageView = (ImageView) findViewById(R.id.image_id);
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) imageView.getLayoutParams();
layoutParams.setMargins(left, top, right, bottom);
imageView.setLayoutParams(layoutParams);
setMargins()'s unit is pixel not dp. If you want to set margin in dp, just inside your values/dimens.xml file create your dimensions like:
<resources>
<dimen name="right">16dp</dimen>
<dimen name="left">16dp</dimen>
</resources>
and access like:
getResources().getDimension(R.dimen.right);
If you use kotlin, this can be simplified by creating an extension function
fun View.setMarginExtensionFunction(left: Int, top: Int, right: Int, bottom: Int) {
val params = layoutParams as ViewGroup.MarginLayoutParams
params.setMargins(left, top, right, bottom)
layoutParams = params
}
Now all you need is a view, and this extension function can be used anywhere.
val imageView = findViewById(R.id.imageView)
imageView.setMarginExtensionFunction(0, 0, 0, 0)
You can use this method, in case you want to specify margins in dp:
private void addMarginsInDp(View view, int leftInDp, int topInDp, int rightInDp, int bottomInDp) {
DisplayMetrics dm = view.getResources().getDisplayMetrics();
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.setMargins(convertDpToPx(leftInDp, dm), convertDpToPx(topInDp, dm), convertDpToPx(rightInDp, dm), convertDpToPx(bottomInDp, dm));
view.setLayoutParams(lp);
}
private int convertDpToPx(int dp, DisplayMetrics displayMetrics) {
float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, displayMetrics);
return Math.round(pixels);
}
Answer from 2020 year :
dependencies {
implementation "androidx.core:core-ktx:1.2.0"
}
and cal it simply in your code
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
setMargins(5)
}
create layout dynamically and set its parameter as setmargin() will not work directly on an imageView
ImageView im;
im = (ImageView) findViewById(R.id.your_image_in_XML_by_id);
RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(im.getLayoutParams());
layout.setMargins(counter*27, 0, 0, 0);//left,right,top,bottom
im.setLayoutParams(layout);
im.setImageResource(R.drawable.yourimage)
For me this worked:
int imgCarMarginRightPx = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, definedValueInDp, res.getDisplayMetrics());
MarginLayoutParams lp = (MarginLayoutParams) imgCar.getLayoutParams();
lp.setMargins(0,0,imgCarMarginRightPx,0);
imgCar.setLayoutParams(lp);
sample code is here ,its very easy
LayoutParams params1 = (LayoutParams)twoLetter.getLayoutParams();//twoletter-imageview
params1.height = 70;
params1.setMargins(0, 210, 0, 0);//top margin -210 here
twoLetter.setLayoutParams(params1);//setting layout params
twoLetter.setImageResource(R.drawable.oo);
In Kotlin you can write it in more pleasant way
myView.layoutParams = LinearLayout.LayoutParams(
RadioGroup.LayoutParams.MATCH_PARENT, RadioGroup.LayoutParams.WRAP_CONTENT
).apply {
setMargins(12, 12, 12, 12)
}
Using a method similar to this might save you some headaches in some situations.
If you have two passes of programmatical tinkering with margins it is safer to check if there are already some layoutParams set. If there are some margins already one should increase them and not replace them:
public void addMargins(View v, int left, int top, int right, int bottom) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) v.getLayoutParams();
if (params == null)
params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
int oldLeft = params.leftMargin;
int oldTop = params.topMargin;
int oldRight = params.rightMargin;
int oldBottom = params.bottomMargin;
params.setMargins(oldLeft + left, oldTop + top, oldRight + right, oldBottom + bottom);
v.setLayoutParams(params);
}
Here is an example to add 8px Margin on left, top, right, bottom.
ImageView imageView = new ImageView(getApplicationContext());
ViewGroup.MarginLayoutParams marginLayoutParams = new ViewGroup.MarginLayoutParams(
ViewGroup.MarginLayoutParams.MATCH_PARENT,
ViewGroup.MarginLayoutParams.WRAP_CONTENT
);
marginLayoutParams.setMargins(8, 8, 8, 8);
imageView.setLayoutParams(marginLayoutParams);
We can create Linear LayoutParams & use resources.getDimensionPixelSize for dp value.
val mContext = parent.context
val mImageView = AppCompatImageView(mContext)
mImageView.setBackgroundResource(R.drawable.payment_method_selector)
val height = mContext.resources.getDimensionPixelSize(R.dimen.payment_logo_height)
val width = mContext.resources.getDimensionPixelSize(R.dimen.payment_logo_width)
val padding = mContext.resources.getDimensionPixelSize(R.dimen.spacing_small_tiny)
val margin = mContext.resources.getDimensionPixelSize(R.dimen.spacing_small)
mImageView.layoutParams = LinearLayout.LayoutParams(width, height).apply {
setMargins(margin, margin, 0, 0)
}
mImageView.setPadding(padding, padding, padding, padding)

Categories

Resources