I'm using the thumb of the horizontal scroll view to indicate which page the user is on. What I would like to happen is the thumb width be the screenwidth/number of pages which is what happens on larger devices. The problem comes when I switch to a phone: the thumb width is no longer the size it's bigger which I cannot use.
Is there a way to change the width of the thumb in a horizontal scroll view (or the hight in a vertical scroll view)?
So I figured it out. You cannot change the actual scrollviews scrollbars because you need the class ScrollBarDrawable which isn't in the ADK. So what I did was overrode the scrollview and drew a custom scrollbar. Also make sure to disable the scrollviews default scrollbars (View.setVericalScrollbarEnabled(boolean) or android:scrollbars="none")
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w,h,oldw,oldh);
width = getWidth() - getPaddingLeft() - getPaddingRight();
//you need this to get the total width of the scrollview (with all of the children)
measure(w,h);
totalWidth = getMeasuredWidth();
}
#Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
float xPer = getScrollX() / totalWidth;
canvas.drawRect(
(xPer * width) + getScrollX(),
getHeight() - scrollBarHeight,
//scroll position //width of the bar //offset in the actual canvas
((xPer * width) + (width/(totalWidth/width)) + getScrollX(),
getHeight(), paint);
}
Hope this helps someone else!
Related
Given a simple RelativeLayout like this:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#0fffff">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="#drawable/img001" />
</RelativeLayout>
the left/top spacing between the layout border and the image border depends on the W/H ratio of the image being load in the imageView.
How can I know (programmatically) the real margin (width and height of the cyan area) after an image is shown in this layout?
This method will calculate the new rectangle which bounds the object after FIT_CENTER and all other related values.
It should work on all cases of object and container.
public static Rect calculateFitCenterObjectRect(float containerWidth, float containerHeight, float objectWidth, float objectHeight) {
// scale value to make fit center
double scale = Math.min( (double)containerWidth / (double)objectWidth, (double)containerHeight / (double)objectHeight);
int h = (int) (scale * objectHeight); // new height of the object
int w = (int) (scale * objectWidth); // new width of the object
int x = (int) ((containerWidth - w) * 0.5f); // new x location of the object relative to the container
int y = (int) ((containerHeight - h) * 0.5f); // new y location of the object relative to the container
return new Rect(x, y, x + w, y + h);
}
You can use FrameLayout to position the view wherever you want after using the previous method with the new x, y, width, height of the scaled object.
If you know the width of the ImageView, like this
int ivWidth = iv.getMeasuredWidth();
and the total width of the layout (your RelativeLayout), like this
int layoutWidth = yourLayout.getWidth();
then, you can easily get the horizontal margin, like this
int horizontalMargin = (layoutWidth - ivWidth)/2;
And the same goes for height.
You should call functions like getWidth and getHeight after the dimensions of your layout have been calculated, as described by Veer's and Khan's answer on How to get the width and height of an Image View in android?.
Calling getWidth or getHeight in onCreate will return 0.
I'm trying to figure out how to draw a Square within my onDraw method in Android.
The square must be positioned in the exact center of the canvas
(Not the screen)
The padding/spacing on the left and right hand side of the square should be
equal
The padding/spacing on the top and bottom of the square should be equal
The size of the square should be relatively large, about 90% of the
canvas's width
Here's what I have so far.
//this.rect is an instance of Rect() which later gets called in the canvas.drawRect() method
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = this.getMeasuredWidth();
int height = this.getMeasuredHeight();
int padding = (width / 10);
this.size = width - padding;
this.rect.set(padding,padding,size,size);
}
The code above draws the square but I'm not sure how to get it to center in the canvas. I am also open to using another technique that does not involve using a Rect.
What properties do I need to set to this Rect() in order for the canvas.drawRect(rect,paint) to draw the rectangle directly in the center of the canvas?
Edit:
Terribly drawn example of what I want to achieve
Assuming width is the width of the canvas, I guess you're missing substracting the padding twice.-
this.size = width - padding * 2;
EDIT
Since we're talking about a rectangle here, you'll need to do some more changes to your code, and calculate different top and left padding .-
int width = this.getMeasuredWidth();
int height = this.getMeasuredHeight();
int paddingLeft = (width / 10);
size = width - paddingLeft * 2;
int paddingTop = (height - size) / 2;
this.rect.set(paddingLeft,paddingTop,size,size);
EDIT 2
Maybe a clearer approach would start calculating the size of your square.-
size = width * 0.9f;
int paddingLeft = (width - size) / 2;
int paddingTop = (height - size) / 2;
this.rect.set(paddingLeft,paddingTop,size,size);
I've got a tiled pan-n-zoom component that uses several FrameLayouts to position image tiles (that scale), markers (that move, but don't scale) and controls (which neither move nor scale). It works fine.
Markers are positioned in a FrameLayout with topMargin and leftMargin. So far so good.
When a marker is touched, I need to open a little popup, at the same position as the marker that was touched but offset by the dimensions of the popup. That's to say that if the popup is 100 pixels wide and 50 pixels tall, and the marker touched was at 800 x and 1100 y, the popup should be at 750 x (postion of marker minus half the width of the popup) and 1050 y (position of the marker minus the full height of the popup). The effect is like a tooltip - a little nub points down at the marker, etc.
The popup dimensions are flexible, based on the text to be displayed, and need to be calculated.
Obviously the dimensions aren't available until after layout happens. What's the best way to get these dimensions and react accordingly?
(should mention that a RelativeLayout is not an option)
TYIA.
/EDIT
looks like I can get the dimensions of the children in onMeasure and onLayout, but re-applying a new layout in one of these handlers would create an infinite loop - setting a flag to catch just the first pass did not work. i guess the updated question would be "now that I know where I can get the information, how should I react and position it?"
the answer is to manage positioning by override onLayout of the containing ViewGroup, rather than the View itself.
E.g.,
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
MyCustomLayout.LayoutParams lp = (MyCustomLayout.LayoutParams) child.getLayoutParams();
int w = child.getMeasuredWidth();
int h = child.getMeasuredHeight();
int x = lp.left - (int) (w / 2f);
int y = lp.top - h;
child.layout(x, y, x + w, y + h);
}
}
}
(note that the above example specifically is untested, but i've tested the premise and it works)
I am using Canvas.drawCircle to draw a circle in Android laout.
Method gets 3 parameters - first two are position - x and y.
Is it possible to skip hardcoded position of the circle and draw it centered ?
Following code can be used to get the width and height of the screen.
int width = this.getWidth();
int height = this.getHeight();
To draw circle in the middle of screen you can call :
Canvas.drawCircle(width/2, height/2)
You can paint a circle centered to the screen like this:
Display disp = ((WindowManager)this.getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
canvas.drawCircle(disp.getWidth()/2, disp.getHeight()/2, radius, paint);
Assuming you are extending the View class:
int CentreX = (this.getWidth() / 2);
int CentreY = (this.getHeight() / 2);
I am drawing a Drawable to a custom view in android.
When the custom view is displayed the parent is a ScrollView. When the scrollview moves the Drawables shrink until they get off screen and then get bigger as you scroll back to the custom widget even though its explicitly set at 219dip square.
The reason seems to be the way I'm getting the bounds in the onDraw(Canvas canvas) method
int mRight;
int mLeft;
int mBottom;
int mTop;
mRight = canvas.getClipBounds().right;
mLeft = canvas.getClipBounds().left;
mBottom = canvas.getClipBounds().bottom;
mTop = canvas.getClipBounds().top;
int availableWidth = mRight - mLeft;
int availableHeight = mBottom - mTop;
It seems that the ClipBound changes to reflect how much of the view is on the screen. Therefore resize the Drawables until it gets really small and goes off screen.
I tried to replace the code above with this
int availableWidth = canvas.getWidth();
int availableHeight = canvas.getHeight();
Nothing is drawn to the screen now? shouldn't this work?
When drawing my custom Drawable I use:
float w = this.getBounds().width();
float h = this.getBounds().height();
to get the bounding area of the my Drawable in the draw(Canvas canvas)method. I have not tried this in a ScrollView, but I would think that the bounds of the Drawable should work the same either way.
Hope this helps.
This works for my custom View, this code goes in the onDraw(Canvas canvas) method.
mRight = this.getRight();
mLeft = this.getLeft();
mBottom = this.getBottom();
mTop = this.getTop();
int availableWidth = mRight - mLeft;
int availableHeight = mBottom - mTop;
previous answer was wrong, view has no method getBounds()