I am using a custom view (CoordinateGridView) in XML like this:
<com.android.catvehicle.CoordinateGridView
android:id="#+id/coordinateGrid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
I am trying to get the width of the CoordinateGridView to fill the entire width of the screen. The height should then match the width -- therefore, the custom view should always be drawn as a square.
How do I do this?
Override the onMeasure function in CoordinateGridView:
public void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
setMeasuredDimension(size, size);
}
See https://github.com/chiuki/android-square-view for a full example.
Related
I have a ListView with visibility=gone and height=wrap_content, and i need its height to can make an animation of expand.
I already tried it:
view.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
int height = view.getMeasuredHeight();
and
v.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
int height = view.getMeasuredHeight();
and
v.measure(View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.MATCH_PARENT, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT, View.MeasureSpec.UNSPECIFIED));
int height = view.getMeasuredHeight();
But it returned me a lesser value.
I am trying to do this after onResume.
The only way that i found was setting the width of the my view from width of a visible header view, then the below code returned me the right value.
int widthSpec = MeasureSpec.makeMeasureSpec(headerView.getWidth(), MeasureSpec.EXACTLY);
int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
v.measure(widthSpec, heightSpec);
int height = v.getMeasuredHeight();
view.post(new Runnable() {
#Override
public void run() {
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int height = view.getMeasuredHeight();
}
});
This worked for me. The method "post" makes sure the view is already added to the screen.
There is only one efficient way to do that if you want to animate height of a view whose visibility is gone
First add this in xml of hidden view
android:animateLayoutChanges="true"
then thats how you can set it to animate
yourView.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
Android will animate any layout change on that specific view
When an object is gone, it no longer is part of the layout. Maybe you mean to set your object to invisible, in which case you'll probably get a sensical value
This works for me
view.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
int height = view.getMeasuredHeight();
this is my first post. I am learning to code in java for android apps.
I am using a LinearLayout "variable named: ll" with a predefined layout_weight (which I want to change whenever I want in the future) and height and width set to MATCH_PARENT. I want to get the height of this LinearLayout in pixels. I fill this using java (ll.addView(variableForAnObject);).
I am trying to get its height using ll.getLayoutParams().height; but I am getting -1. Because I believe this is the constant for MATCH_PARENT. Setting the height to 0dp makes the ll invisible and gives height as 0.
Please tell me if there's a way to get its height. I think I can do this by getting screen height using DisplayMetrics and making nearly impossible calculations (for me, at least) but this will be too complex.
try with ll.getHeight() should work
if not, it's because android has not yet calculed its bounds, then:
//inside of onCreate method should work
ll.post(new Runnable() {
#Override
public void run() {
//maybe also works height = ll.getLayoutParams().height;
height = ll.getHeight();
}
});
It is -1 because its dimensions have not yet been set, whenever you set layout it takes some time to compute the actual values including height, width etc.
Use OnLayoutListener to listen when it has finished with the layout.
layout.onLayoutChange (View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
//Extract values here
height = view.getHeight();
width = view.getWidth()
}
See this for more about the OnLayoutListener
Define your LinearLayout in your class and use getHeight() and getWidth(). Example:
LinearLayout yourLayout = (LinearLayout) findViewById (R.id.yourLL);
double height = yourLayout.getHeight();
double width = yourLayout.getWidth();
Hope it helps! :)
Give the id field in your layout xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="#+id/<ID>>
Use this id to get reference in java class and find height and width:
LinearLayout linearLayout= (LinearLayout) findViewById (R.id.<ID>);
double height = linearLayout.getHeight();
double width = linearLayout.getWidth();
I've got a custom view (called CustomStrechView) which extends an ImageView. The point of this view is so that I can get an image to fill the view without losing the aspect ratio.
Now the CustomStrechView works fine when I use it in most applications, but when I try to apply it within my HorizontalScrollView, the images all seem to disappear. I'm not sure why this happens. I've tried removing the <HorizontalScrollView /> and when I do the images show back up, so I feel there is some property that needs to be set, but I can't seem to find it.
Can anyone point out what I’m doing wrong or a better way to get a custom view to work in a HorizontalScrollView?
Edit:
After playing around with this for a bit, I've determined that I can get the custom view to show the image only if I hardcode the width dimension, ie:
<com.example.dragdropshapes.CustomStrechView
android:layout_width="200dp"
Leaving the height as fill_parent is fine...
Code:
Here's how my custom view is being used in the xml file:
<!-- Removing this makes the images show up -->
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:layout_marginTop="50dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:showDividers="middle"
android:orientation="horizontal">
<!-- Changing this to a normal ImageView makes the image show up -->
<com.example.dragdropshapes.CustomStrechView
android:id="#+id/pickshapes"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:clickable="true"
android:onClick="pickShapes"
android:background="#drawable/border"
android:src="#drawable/ic_launcher"
/>
<!-- There are 5 other custom ImageViews here -->
</LinearLayout>
</HorizontalScrollView>
Here's the major part of the custom view code:
public class CustomStrechView extends ImageView{
private final Drawable srcPic;
private final String TAG = "strechyTag";
private boolean changeSize = false;
private int Xpx;
private int Ypx;
public CustomStrechView(Context context) {
super(context);
srcPic = this.getDrawable();
}
//... other constructors, not really important...
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
Log.d(TAG, "in the onMeasure!!\n");
int width, height;
width = MeasureSpec.getSize(widthMeasureSpec);
height = width * srcPic.getIntrinsicHeight() / srcPic.getIntrinsicWidth();
setMeasuredDimension(width, height);
}
}
Through some debugging I was able to at least partially solve this myself. Turns out that the width acquired from the MeasureSpec.getSize(widthMeasureSpec); call was 0. Thus the calculation ended in width and height being 0 and the setMeasuredDimension call would then make the image invisible.
Now I'm saying I have this partially solved, because I still don't understand why I was getting that value of 0. I think it's because in a HorizontalScrollView the width isn't determined (it depends on the content within) thus whatever MeasureSpec.getSize(widthMeasureSpec); is actually doing is talking to the parent, and the parent in a normal Linear or RelativeLayout has a defined width where as in a HorizontalScrollView it does not... but that's just speculation at this point.
So I made a fix for it, if the width is 0 we run the calculation via the height instead. The height needed two cases to cover it to avoid divide by 0 errors (the else if and the else collectively).
Here's my current solution with the same xml file I noted in the Question.
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if(width > 0)
height = width * srcPic.getIntrinsicHeight() / srcPic.getIntrinsicWidth();
else if(srcPic.getIntrinsicWidth() < srcPic.getIntrinsicHeight())
width = height / (srcPic.getIntrinsicHeight() / srcPic.getIntrinsicWidth());
else
width = height / (srcPic.getIntrinsicWidth() / srcPic.getIntrinsicHeight());
setMeasuredDimension(width, height);
}
I'm having trouble trying to set a specific size for the width of my custom view. I know I can just hard-code a value in the layout_width field in the XML file but I'm trying not to result to hard-coding values. I need my View to be half the size of the screen. So, within the class I find half the screen size:
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
try{
Point size = new Point();
display.getSize(size);
screenWidth = size.x;
}catch(NoSuchMethodError e){
screenWidth = display.getWidth();
}
Then, I call:
measure(width|MeasureSpec.EXACTLY, LayoutParams.WRAP_CONTENT|MeasureSpec.EXACTLY);
//Where width is equal to half the screen width
but this does not seem to be working for my case. So, to sum it all up, how do you properly specify a particular size for a custom View? Any help will be useful and appreciated! Thanks!
Override the onMeasure() method in your Custom View:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getResources().getDisplayMetrics().widthPixels >> 1;
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Basically, override the width MeasureSpec to be exactly half the width of the screen, then pass that through to the superclass.
I believe that you might not be able to accurately get the width of the screen at this point because you need to wait till the entire hierarchy (up until the most root view) is laid out. You may need to do something like:
ViewTreeObserver.OnGlobalLayoutListener layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int width = getWidth();
int height = getHeight();
//set layoutparams with those values.
}
};
getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
You can confirm the correctness of this by seeing if the values you're getting when you try getting the display width inside of onMeasure differ from the values you get when the onGlobalLayout callback is invoked.
Let's say I have decided to implement my own widget from the base Canvas class in SWT.
I'd like it to have a fixed height of 10 and allow any type of width as long as it conforms to a multiple of 10.
Is there any way to impose this, so the users of my widget will only be allowed to set this kind of values when using my widget in design-mode?
I've tried looking up in ControlEvent on ControlListener, but it doesn't seem to have a way of canceling a resize.. maybe I have to manually set it back to an acceptable value if I detect a width / height?
Thanks
I can suggest you to control the layout of your widget. Implement own Layout with fixed height and ignore any layout set by user.
When you override computeSize, just ignore the width and height hints if they're outside your allowed bounds. For example:
public Point computeSize(int wHint, int hHint, boolean changed)
{
int width, height;
/* We can only be 10px tall */
height = 10;
/* Width must be at least 10px */
if (width < 10)
width = 10;
/* Width must be a multiple of 10px */
else
width -= (width % 10);
return new Point(width, height);
}