I have a custom View which has bigger height than its inner drawn content. I tried to set desired content height manually in code like this:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int chosenWidth = chooseDimension(widthMode, widthSize);
int chosenHeight = chooseDimension(heightMode, heightSize);
int chosenDimension = Math.min(chosenWidth, chosenHeight);
centerX = chosenDimension / 2 - offsetCenterX;
centerY = chosenDimension / 2 - offsetCenterY;
setMeasuredDimension(chosenDimension, chosenDimension - 200); //IN HERE I`M TRYING TO CROP THE VIEWS HEIGHT
}
But it appears that my View scales down. I do not need this.
My solution to this was to reset ALL the dimensions in dimen.xml, but it kinda wrong. Any idea how to crop it in a right and easy way?
Here it is a picture what I want to cut off
Well, I would not have to cut off that space. Just set the correct values in onMesaure(). And to scale all dimens in dimens.xml
Related
I am creating a custom view which extends LinearLayout. I'm adding some shapes to the linear layout, currently with a fixed value of space between them. I'm doing so by defining a LayoutParams and setting the margins to create the space between the shapes.
What I want to do is span them at an equal space across the entire screen so they would fill it, but only if the width of the view is set to either match_parent or fill_parent. If it's set to wrap_content then the original fixed value of space should be set.
I've tried doing:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
spaceBetweenShapesPixels = (parentWidth - shapeWidth * numberOfShapes) / numberOfShapess;
}
However, the method seems to be called twice - Once for the width and height of the parent and after that for the View's itself and when it's for the view itself, the space gets a 0 value.
So how can I just make this logic:
if(width is wrap_content)
{
space = 10;
}
else
{
space = (parentWidth - shapeWidth * numberOfShapes) / numberOfShapess;
}
You should use WidthMode and HeightMode
In the onMeasure() method. Below is sample a from one of my projects
#Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int measuredWidth = 0, measuredHeight = 0;
if (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST) {
measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
}
if (heightMode == MeasureSpec.EXACTLY) {
measuredHeight = MeasureSpec.getSize(heightMeasureSpec);
} else if (heightMode == MeasureSpec.AT_MOST) {
double height = MeasureSpec.getSize(heightMeasureSpec) * 0.8;
measuredHeight = (int) height;// + paddingTop + paddingBottom;
}
}
MeasureSpec.EXACTLY - A view should be exactly this many pixels regardless of how big it actually wants to be.
MeasureSpec.AT_MOST - A view can be this size or smaller if it measures out to be smaller.
MeasureSpec.UNSPECIFIED - A view can be whatever size it needs to be in order to show the content it needs to show.
Refer this for more details https://stackoverflow.com/a/16022982/2809326
I know it's bit tricky and still thinking whether is it possible or not, but i want to make my image to adjust without decreasing in image quality on any android device when i used vector Drawable it was pretty convenient but sometimes size of vectors are not memory efficient so i don't want to use them.Though i want to know if there is any way to adjust simple PNG or JPEG files irrespective of resolution and screen size in Android?
If anyone can give me way,it would be great help !!
Use Resize Image View (Custom Image View)
public class ResizableImageView extends ImageView {
public ResizableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ResizableImageView(Context context) {
super(context);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable d = getDrawable();
// get drawable from imageview
if (d == null) {
super.setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
return;
}
int imageHeight = d.getIntrinsicHeight();
int imageWidth = d.getIntrinsicWidth();
// get height and width of the drawable
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
// get width and height extracts the size from the supplied measure specification.
float imageRatio = 0.0F;
if (imageHeight > 0) {
imageRatio = imageWidth / imageHeight;
}
float sizeRatio = 0.0F;
if (heightSize > 0) {
sizeRatio = widthSize / heightSize;
}
int width;
int height;
if (imageRatio >= sizeRatio) {
// set width to maximum allowed
width = widthSize;
// scale height
height = width * imageHeight / imageWidth;
} else {
// set height to maximum allowed
height = heightSize;
// scale width
width = height * imageWidth / imageHeight;
}
setMeasuredDimension(width, height);
// This method must be called to store the measured width and measured height. Failing to do so will trigger an exception at measurement time
}
}
I am creating a triangle (Custom View) and then adding it to the parent view (RelativeLayout). i am facing problem here was view taking full screen of parent, how can i set the size of custom view upto that boundaries. triangle extends from view and it has touch listeners. dynamically i'm changing the size of the triangle.
i was added onMeasure() to that view but it takes some fixed amount of width and height..
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d(TAG, "Width spec: " + MeasureSpec.toString(widthMeasureSpec));
Log.d(TAG, "Height spec: " + MeasureSpec.toString(heightMeasureSpec));
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int chosenWidth = chooseDimension(widthMode, widthSize);
int chosenHeight = chooseDimension(heightMode, heightSize);
int chosenDimension = Math.min(chosenWidth, chosenHeight);
setMeasuredDimension(chosenDimension, chosenDimension);
}
i want set the width and height of custom view depending on the size of view when user change how much it has. look at the image.
It does not matter where the points are. You can draw the triangle of any orientation. But the custom view will always be a rectangular. If you do not draw anything outside the triangle the view will appear triangular.
I've created a custom View that implements onMeasure:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
float width = MeasureSpec.getSize(widthMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
float height = MeasureSpec.getSize(heightMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
float nominalHeight = getResources().getInteger(R.integer.nominalheight);
float nominalWidth = getResources().getInteger(R.integer.nominalwidth);
float aspectRatio = nominalWidth / nominalHeight;
if( width / height > aspectRatio //too wide
&& (
widthMode == MeasureSpec.AT_MOST ||
widthMode == MeasureSpec.UNSPECIFIED
)
) {
width -= (width - height * aspectRatio);
}
if( width / height < aspectRatio //too tall
&& (
heightMode == MeasureSpec.AT_MOST ||
heightMode == MeasureSpec.UNSPECIFIED
)
) {
height -= (height - width / aspectRatio);
}
setMeasuredDimension((int)width, (int)height);
}
The intention is, where possible, to create a rectangle whose aspect ratio is the same as the one specified by nominalheight and nominalwidth. Obviously if the function is passed MeasureSpec.EXACTLY then it should lay out with the dimension given in that direction.
I'm laying this View out with WRAP_CONTENT in the xml in both directions. What's puzzling me is that, stepping through the onMeasure calls, half of them show MeasureSpec.AT_MOST and the routine calculates the correct rectangle, and the other half show MeasureSpec.EXACTLY and it obviously uses the given dimensions. Even more puzzlingly, if I disable the conditionality (I would assume, from documentation and the example code, incorrectly) it works fine.
Why am I getting these alternating calls with different values, and how can I persuade Android to lay my View out in the correct dimensions?
I made a custom view. If I add the view to the layout XML file and I set the height to fill_parent "specSize" return 0. Why?
Code:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredHeight = 90;
int specMode = MeasureSpec.getMode(heightMeasureSpec);
int specSize = MeasureSpec.getSize(MeasureSpec.getMode(heightMeasureSpec));
if(specMode != MeasureSpec.UNSPECIFIED){
measuredHeight = specSize;
}
setMeasuredDimension(60, measuredHeight);
}
Does anyone know how I can get the height of fill_parent?
You don't need to call MeasureSpec.getMode inside of call to 'getSize' whole idea of measure spec is to combine way of measuring ( knowing as Spec) and associated Size. See documentation for MeasureSpec.makeMeasureSpec method.So correct code will look something like:
int widthSpec = MeasureSpec.getMode(widthMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
The correct code will be:
int specMode = MeasureSpec.getMode(heightMeasureSpec); ----This was already correct
int specSize = MeasureSpec.getSize(heightMeasureSpec); ----This is corrected.