How to get the current Y offset of a ScrollView - android

ScrollView has a method for setting the x and y scroll offset, but no method for getting the current offset (all I'm really interested is the y offset, since ScrollView only supports vertical scrolling). I don't see any method that would work in the superclasses, and tried getTop() for the content view, which is always zero. Am I missing something?

Call getScrollY() on the ScrollView
See here for the documentation: http://developer.android.com/reference/android/view/View.html#getScrollY%28%29

Why don't you try something like this ?
targetScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
int scrollX = targetScrollView.getScrollX();
Log.d(TAG, "scrollX: " + scrollX);
}
});

If you are certain that you should get some value after using getScrollY() or getTop(), try to put those method inside a
yourScroolView.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"Current Y is : "+getScrollY,Toast.LENGTH_SHORT).show();
}
});
Now it should work. According to my understanding about this method, it will only run after the layout being drawn. That can be one of the reason why you kept getting 0 previously. Hope it helps.

What about: computeHorizontalScrollOffset() and computeVerticalScrollOffset().

I achieve to get by the following. First get screen heigh and width.
DisplayMetrics metrics = getResources().getDisplayMetrics();
float screenWidth = metrics.widthPixels;
float screenHeight = metrics.heightPixels;
then to find out the document height (the total, what is being shown and what is out of the screen)
public float getDocumentHeight(){
return (computeVerticalScrollRange() * screenHeight)/computeVerticalScrollExtent();
}
Finally to get the offset
public float getTopY(){
return (getDocumentHeight() * computeVerticalScrollOffset())/computeVerticalScrollRange();
}
This give you the top of the window relative to the part of the document you are seeing so you could find the exact position of an event by
public boolean onTouchEvent(MotionEvent event) {
int y = event.getY() + (int) getTopY();
}
You can also do something similar to handle the width

Related

Android - Adding an item to a scroll view and scroll programmatically

I have an empty scrollview. I create with inflater a text view, add it to the ScrollView programmatically and then do:
rsView.smoothScrollBy((viewLeft + viewWidth / 2) - center, 0);
BUT viewLeft and viewWidth are 0 as the view is not measured yet. Any suggestions on how to make it scroll the view properly?
In this post: getWidth() and getHeight() of View returns 0 you have a lot of good options to solve this problem. Particularly I use this one:
Listen to Draw/Layout Events: ViewTreeObserver
A ViewTreeObserver gets fired for different drawing events. Usually the OnGlobalLayoutListener is what you want for getting the measurement, so the code in the listener will be called after the layout phase, so the measurments are ready:
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
rsView.smoothScrollBy((viewLeft + viewWidth / 2) - center, 0);
}
});
Move the smoothScrollBy() call to a Runnable and post that to the new TextView's handler after it's been added, which will cause it to run after it's been laid out. For example:
viewGroup.addView(childView);
childView.post(new Runnable() {
#Override
public void run() {
rsView.smoothScrollBy((childView.getLeft() + childView.getWidth() / 2) - center, 0);
}
}
);
I'm not sure how you're calculating center, but if it depends on the new TextView's dimensions, you'll need to move the calculation to the Runnable, as well.

how to get position of Edittext in RelativeLayout or alternate method for getY()

I am trying to set my EditTest on specific position in RelativeLayout. So i am getting position of Ediitext and set according what i want. It's working fine with me. But problem is occur when Android 2.2 and android 2.3 devices didn't find getY() method. because i am trying to get the position of Ediitext.
Now i need to find another method for this because it's not working in 2.2 and 2.3.
Here is my code for reference.
ViewTreeObserver autoCompleteObserver = myAutoComplete.getViewTreeObserver();
autoCompleteObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
relativeLayoutHeight = ((int) myAutoComplete.getY()-12);
}
});
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
Log.i("TEST", "GLOBAL LAYOUT "+activityRootView.getHeight());
Log.i("TEST", "GLOBAL LAYOUT rel"+relativeLayoutHeight);
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
Log.i("TEsT","Keyboard visible");
myRelativLayout.scrollTo(0, relativeLayoutHeight);
}
else
{
Log.i("TEsT","Keyboard not visible");
myRelativLayout.scrollTo(0, 0);
myAutoComplete.setDropDownHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
}
}
});
}
This code working fine in 4.1 but i need to find alternate method for getY() which return me position of EditText.
Give me any reference or hint.
Have a look at the getY() method from View class in android 4.1: Link
/**
* The visual y position of this view, in pixels. This is equivalent to the
* 'translationY' property plus the current
* 'top' property.
*
* #return The visual y position of this view, in pixels.
*/
public float getY() {
return mTop +
(mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
}
On Android 2.2 & 2.3, there's a similar method called getTop(): Link
/**
* Top position of this view relative to its parent.
*
* #return The top of this view, in pixels.
*/
public final int getTop() {
return mTop;
}
So, if you are not applying any translations to your EditText (using View#setTranslationY(float) etc.), getY() and getTop() will provide essentially the same result.
Add this code inside your onGlobalLayout
int[] locations = new int[2];
yourView.getLocationOnScreen(locations);
int x = locations[0];
int y = locations[1];//returns Y position

How to get Coordinates on touch Event on bitmap not of Screen

Greets ,
How can I get the Coordinates of the Bitmap not of the screen. Screen Coordinates got by event.getX(),event.getY() methods but not getting coordinates of the bitmap. Please help anyone.
You can't get the coordinates of the bitmap directly. You need to calculate to yourself.
Use the position of the ImageView, and with that you can handle it.
Of course, when you are after Activity onCreate you can acces to any inflated (active) views parameter.
Exemple.
ImageView a;
a.getPaddingBottom();
Like all coordinats (left right etc...)
After this you need the Height and Width of the ImageView.
Nah, when you know the views position, hegiht and width you can calculate.
Example:
final ImageView iv_YourImage = (ImageView) findViewById(R.id.iv_imageview);
public boolean onTouch(View v, MotionEvent event){
int topParam = iv_YourImage.getPaddingTop();
int rightParam = iv_YourImage.getPaddingRight();
int maxTopParam = topParam+iv_YourImage.getMaxHeight();
int maxRightParam = rightParam + iv_YourImage.getMaxWidth();
if(event.getX>topParam&&event.getX<maxTopParam){
//the x coordinate is in your image... do the same to Y
}
return true;
}
look at the following code if the answer is too short:
Android: Detect touch on actual image in ImageView
the code replaces the padding and max height coding of this answer and replaces it with the actual width and height of the displayed image using getWidth() and getHeight(). And uses the screen width and height to calculate its position. If you want more detailed answers for your problem you should give more information such as where did you draw the bitmap... did you define it at the activity XML or did you draw it at a random location such as at the X and Y coordinates of a touch event, the answer depends on that information.
package com.example.img;
imports....
public Image extends Activity {
ImageView imgYourImage;
// int imgWidth;
// etc...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image);
imgYourImage = (ImageView) findViewById(R.id.yourImage);
imgDimension();
}
private void imgDimension() {
imgWidth = imgYourImage.getWidth();
// at newer api's you can use getLeft() and getTop() of imageView
// if getLeft() works you have the leftX coordinate of image already.
// do same with height
// also get the screen Width and Height by display.getWidth() (depreciated)
// Or the newer code display.getSize()
leftX = (screenwidth - imgWidth) / 2;
rightx = leftx + imgWidth;
}
Notice that this code only works when the image is displayed at the horizontal center of the screen. Or use top and bottom if the image is displayed at the vertical center of the screen.

Detect if Webview scroll reach the end

am trying to figure out the max scroll position that the WebView can reach, i've tried the webView.pageDown(true) but the result is delayed ( i cant scroll it down, then up infront of the user, and this method doesn't work every time), i've tried also webView.getContentHeight() and the height isn't correct for Arabic content.
Please Advice
ok, i figured out the answer
you can get the real content height using
(int) Math.floor(webView.getContentHeight() * webView.getScale());
when you get the real height, then just override the scroll method in webview to listen to scroll event, if the scroll reach the real height, your webview is in the bottom of the scroll.
#Override
public void onScroll(int l, int t) {
int height = (int) Math.floor(webView.getContentHeight() * webView.getScale());
int webViewHeight = webView.getHeight();
int cutoff = height - webViewHeight - 10; // Don't be too strict on the cutoff point
if (t >= cutoff) {
setDisclaimerButtonEnabled(true);
}
}
The non-strictness is required, is because I found on the Samsung S5 the bottom most scroll value was only 1 pixel value away from the bottom most value!
Loading / Visible button only when webview reached / scrolled to bottom.
Create JavaScript class :
public class JavaScriptInterface {
#android.webkit.JavascriptInterface
public void didScrollToBottom() {
Log.d(TAG, "Scroll to Bottom");
myHandler.post(new Runnable() {
#Override
public void run() {
btnAccept.setVisibility(View.VISIBLE);
}
});
}
}
In onCreate() :
final JavaScriptInterface jsInterface = new JavaScriptInterface();
myWebView.addJavascriptInterface(jsInterface, "AndroidFunction");

Android: Notify Scrollview that it's child's size has changed: how?

When I enlarge the size of the content of a scrollview, the scrollview takes a while to get to "know" this size change of it's child. How can I order the ScrollView to check it's child immediately?
I have an ImageView in a LinearLayout in a ScrollView.
In my ScaleListener.onScale, I change the size of my LinearLayout. I then try to order a scroll on the scrollview. In the ScaleListener.onScale:
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) imageView.getLayoutParams();
params.width = (int) (startX * scaleFactor);
params.height = (int) (startY * scaleFactor);
imageView.setLayoutParams(params);
(...)
scrollView.scrollBy(scrollX, scrollY);
However, no scrolling occurs when in the situation before the scaling scrolling was not possible because the view was too small to scroll. After the setLayoutParams, the view should be larger, but no scrolling occurs because the scrollview thinks the child is still small.
When a fes ms later the onScroll is called again, it does scroll fine, it somehow found out that the child is larger and scrollable.
How can I notify the scrollview immediately, that the child's size has changed? So that scrollBy will work right after setLayoutParams on it's child?
I found a solution after trying just about every onXXX() method. onLayout can be used. You can plan the scroll and do it later in onLayout().
Extend your scrollview, and add:
private int onLayoutScrollByX = 0;
private int onLayoutScrollByY = 0;
public void planScrollBy(int x, int y) {
onLayoutScrollByX += x;
onLayoutScrollByY += y;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
doPlannedScroll();
}
public void doPlannedScroll() {
if (onLayoutScrollByX != 0 || onLayoutScrollByY != 0) {
scrollBy(onLayoutScrollByX, onLayoutScrollByY);
onLayoutScrollByX = 0;
onLayoutScrollByY = 0;
}
}
Now, to use this in your code, instead of scrollBy(x,y) use planScrollBy(x,y). It will do the scroll at a time when the new size of the child is "known", but not displayed on screen yet.
When you use a horizontal or vertical scrollview, of course you can only scroll one way, so you will have to change this code it a bit (or not, but it will ignore the scroll on the other axis). I used a TwoDScrollView, you can find it on the web.
You can call:
scrollView.updateViewLayout(childView, childLayout)

Categories

Resources