Scrolling of View happens after the position of scroll by touch - android

I have a customised View in an android application which is put inside a HorizontalScrollView as shown.
<HorizontalScrollView
android:id="#+id/feedBackScroller"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
<com.my.views.OfflineFeedbackView
android:id="#+id/feedBackView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="#dimen/session_rec_page_title_bar_height"
android:layout_marginBottom="#dimen/session_rec_page_ctrl_bar_height"/>
</HorizontalScrollView>
The OfflineFeedbackView shows the pitch track of the audio track that I am playing and I scroll this view by calling scrollTo(newXPos, newYPos) based on the current time of the playback. The problem that I am facing is that if I scroll the screen by touching and then start the playback, the reference of scrolling seems to get changed on my view and the scrolling takes place from the position to which I scrolled to by touch. I went through the API docs and found that the scrollTo(newXPos, newYPos) internally calls onScrollChanged(int l, int t, int oldl, int oldt) where oldl and oldt are the old horizontal and vertical origins respectively. So, what I am interpreting from this is that when I scroll by touching on the screen these origin values get changed. So, I also tried calling onScrollChanged(newX, newY, 0, 0) but this just freezes the screen and there is no scroll. Am I doing something wrong? What can be other better ways to handle this?

Here problem looks like as you said HorizontalScrollView positions gets changed when you touch.
So one solution may be find the initial top-left position of your scroll view
HorizontalScrollView hsv = (HorizontalScrollView) findViewById(R.id.ScrollView);
int x, y;
x = hsv.getLeft();
y = hsv.getTop();
and always scroll your child view relative to these stored x,y positions i.e
childView.scrollTo(x+newXPos,y+newYPos);

Related

Is there a method for customizing the positioning and size (width AND height) of a scrollbar for any View?

It seems that every angle I manage to find doesn't end up working in the way I need it to. My goal is to be able to customize the positioning and size of any scrollbar on any view, be it a recyclerview, gridview, or listview. I've tried using layer-list xmls to adjust the height and positioning, a Seekbar turned vertically, as well as trying to create my own scrollbar thumb and track using imageviews.
In terms of the layer-list, it just didn't have an effect on the scrollbar at all. The other two attempts at a solution (using a Seekbar, using individual imageviews) were nearly effective, except I needed the current scrolled position (getScrollY()) to be able to make the scrollbars I made actually accurate instead of just visually being a scrollbar. However, even though getScrollY() is defined for recyclerview, gridview and more, it always returns a 0, so I am unable to get that information (except for scrollviews, perhaps; I believe that's the only view type that properly returns a getScrollY() value).
Is it even possible to customize the scrollbar in this manner? I'd be keen to see references or documentation that can point me in the right direction. It feels like this is generally a non-issue for most developers on Android, or at least in general isn't something many people have asked for.
Edit
To assist in visualizing what I have and what I desire, here's a screenshot of the scrollbar as it is right now:
The following image is marked up to show what my intended outcome for this scrollbar would be:
Views have the capability for a scrollbar but a lot don't show them by default.
So any View has a whole load of XML attributes to customise the appearance, size and position.
But these are useless if not shown.
A lot of ViewGroups sub classes setWillNotDraw to be true and this removes the capability to draw the built in scrollbars of the View.
So to get any view to show it's built in scrollbars you need to the setWillNotDraw(false)
Getting any View to show it's built in scrollbars is Step 1 but again not all Views Calculate automatically the length and position of scroll hence they return 0 for the scroll position.
The View has to implement the following methods and return the appropriate numbers for the scroll position to be correct and things like getScrollY to return more than 0
// Length of scrollbar track
#Override
protected int computeHorizontalScrollRange() {
return (int) value;
}
// Position from thumb from the left of view
#Override
protected int computeHorizontalScrollOffset() {
return (int) value;
}
#Override
protected int computeVerticalScrollRange() {
return (int) value;
}
#Override
protected int computeVerticalScrollOffset() {
return (int) value;
}
Off Course some View sub classes don't use the built in ones but draw there own.

How to set the four parameters of View.layout(l, t, r, b)

I am facing the same problem in this question, but I have difficulty in understanding the exact meaning of the four position parameters in layout(int l, int t, int r, int b). I know they represent left, top, right and bottom respectively relative to parent, but "relative" to where exactly?
For example, if I translate the button down 100 pixel, in order to move the clickable area down 100 pixel should I set
// l t r b
button.layout(0, 100, 0, button.getHeight()+100)
? Does the integer 100 of second parameter mean 100 pixel down relative to the top of parent? Is the fourth parameter means button.getHeight()+100 relative to the top of parent also??? I tested on my device, the clickable area does not move down as I want. I'm very confused here, any help is greatly appreciated.
The parameters to layout are relative to the parent view's upper left corner. X increases as you move to the right and Y increases as you move down. It is not relative to the view's current position.
You probably don't want to call layout on a child view outside of its parent's onLayout method. There are several other bits of internal bookkeeping that happen as a result of calling layout that will change internal state in a way you don't want for simple animations.
Typically layout is called like this:
child.layout(x, y, x + child.getMeasuredWidth(), y + child.getMeasuredHeight());
The parameters are absolute, with (0, 0) at the parent's upper left corner.
But if you're simply moving a view around for animation you probably want to do something more like:
// Adjust horizontally; dx = change in x position
child.offsetLeftAndRight(dx);
// Adjust vertically; dy = change in y position
child.offsetTopAndBottom(dy);
The parameters to the offset* methods are relative to the view's current position.
If you write a ViewGroup class that moves its child views around in this way, remember that you can get a layout request at any time. At that point your ViewGroup's onLayout method will try to position the child based on its usual layout rules and it will need to adjust this positioning to reflect any other accumulated movement you want to preserve.

Change the behaviour of a GridView to make it scroll horizontally rather than vertically

I want to make a UI element like a GridView, I want it's complete functionality but want it to be horizontally scrollable rather than vertically.
By horizontal scroll I mean it should be built that way and not put in a HorizontalScrollView.
My would be Custom GridView will have fixed number of rows say 4-5 and the columns should be extensible based on number of items in the Adapter. You can think of it as the opposite of what the native GridView does, yet it should maintain the functionality.
I have looked at the source code of how a GridView is implemented by Google, but I am able to understand very less and starting to make the View from scratch doesn't seem to be a good idea, since I am afraid I will not be able to do justice to memory optimization's the way Google did it.
I had observed that GridView extends AbsListView, so my question is, is it AbsListView which lets a GridView scroll vertically and add items from the adapter, or is it GridView which adds the vertical scrolling ability? Should I tweak GridView or AbsListView?
It would be even better to know if there's something which already does what I want to do?
This has already been implemented in native Gallery and YouTube app of Android Honeycomb 3.1 and above. So if anyone has an idea, please elaborate.
Snapshot of Honeycomb Gallery app:
Snapshot of Honeycomb YouTube app:
There is setRotation in API 11. You'll have to rotate the gridview by 90 degrees and child views by -90 degrees.
Documentation: http://developer.android.com/reference/android/view/View.html#setRotation(float)
Update:
To get a 3d effect on views following APIs would be useful
setCameraDistance(float) - set the z axis distance(depth)
setRotationX(float) - set the horizontal axis angle
setRotationY(float) - set the vertical axis angle
Set the camera distance to half of the screen height. Then set the rotationX based on the view's location on screen. The rotation angles should be something like (20, 10, 0, -10, -20) from left to right. Later you can play with rotationY angles to get some height perception.
Do all setting in extended GridView's overriden layout method.
#override
void layout(int t, int l, int r, int b) {
super.layout(t, l, r, b);
...
int columnStart = getFirstVisiblePosition()/no_of_columns;
int columnEnd = getLastVisiblePosition()/no_of_columns;
loop from 'columnStart' to 'columnEnd' 'no_of_colmns' times {
// set the camera distance and rotationX to views
// depending on the position of a view on screen.
}
}

GridView Scroll By one row

Hi i am implementing a gridView and i have trouble making it scroll down 1 row at a time with every scroll event.
my grid has a height of 1 row item (items height is 75dp). i don't want scrolling to be left in a middle of a row.
is there a way i can intercept and modify the scroll distance so that it only returns fixed value ex: +-75dp.
i would appreciate any help or suggestions you can give me. tnx
APIv8 has new function, called smoothScrollBy(int distance, int duration)[1]
i think you should catch all scroll events & implement own method to scroll view.
if you want to scroll by 75dp, just convert it to pixels & use function above.
float density = getContext().getResources().getDisplayMetrics().density;
int scrollBy = (int)(density * 75);
smoothScrollBy(scrollBy, 0);
But would be nice to calculate scrollBy from your GridView, instead of using some constant value (like 75dp)
[1]: http://developer.android.com/reference/android/widget/AbsListView.html#smoothScrollBy(int, int)

How can I know which childview is shown on the current Device screen in a scrollview?

How can I know which childview is shown on the current device screen, in a scrollview?
I want to make an infinite Ruler App, so I need to dynamically add and remove view when the view is flipping, but how and where can I find out which childview is shown on the current device screen, so I can add or remove the correct view when I get that childview changed notify?
Or, can anyone who can give me some other idea to realize this function?
I have met this problem too. you can call getlocalonscreen function to get coordinate of view. for example:
1.
view.getlocaloncreen(xy);// xy[0] is x axis, xy[1] is y axis.
2.
int nScreenWid = getwindowsmanager().getdefaultdisplay().getwidth();
int nScreenHei = getwindowsmanager().getdefaultdisplay().getHeight();
3.
if( xy[0] > nscreenWid )
{
// your view is beyond the x axis.
}
if( xy[1] > xxxxhei )
{ // beyond y axis }
Use scrollView.getScrollY() to find how far down the scroll view the scroll point is, and compare that to the heights of the child views (adding them up as you go along) to see which one must be on screen.

Categories

Resources