I've been working on implementing the fading action bar and parallax scrolling into my Android UI in my Xamarin app. I needed to extend my ScrollView, and now it's called a NotifyingScrollView. How do i style my .axml now. I can't just write NotifyingScrollView in my axml,
namespace NightOut.UiComponents
{
class NotifyingScrollView : ScrollView
{
public interface IOnScrollChangedListener
{
void OnScrollChanged(ScrollView who, int l, int t, int oldl, int oldt);
}
private IOnScrollChangedListener mOnScrollChangedListener { get; set; }
public NotifyingScrollView(Context context) : base(context)
{
}
public NotifyingScrollView(Context context, IAttributeSet attrs) : base(context, attrs)
{
}
public NotifyingScrollView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
{
}
[Android.Runtime.Register("onScrollChanged", "(IIII)V", "GetOnScrollChanged_IIIIHandler")]
protected override void OnScrollChanged(int l, int t, int oldl, int oldt)
{
base.OnScrollChanged(l, t, oldl, oldt);
if (mOnScrollChangedListener != null)
{
mOnScrollChangedListener.OnScrollChanged(this, l, t, oldl, oldt);
}
}
}
}
Generic example:
namespace My.Namespace
{
class MyCustomView : View
{
}
}
Is used in following way in .axml
<my.namespace.MyCustomView />
Or in your specific example:
<nightout.uicomponents.NotifyingScrollView />
Do mind case, namespace in .axml is lowercase, classname is same case as C# declaration.
Related
I have an Activity with a scroll view and 2 buttons, When open this activity both buttons are disabled. What I want is, when I reach the end of the scroll view, enable both buttons to user to accept or decline the content. How can I do this in simple way.
Button before enabled
Thanks in advance.
I have done this things with webView here is my code, hope it will help you.
webView.setOnScrollChangedCallback(new ObservableWebView.OnScrollChangedCallback() {
#Override
public void onScroll(int l, int t) {
int tek = (int) Math.floor(webView.getContentHeight() * webView.getScale());
if (tek - webView.getScrollY() <= webView.getHeight() + 5) {
// enable your button
}
}
});
this is the class
public class ObservableWebView extends WebView
{
private OnScrollChangedCallback mOnScrollChangedCallback;
public ObservableWebView(final Context context)
{
super(context);
}
public ObservableWebView(final Context context, final AttributeSet attrs)
{
super(context, attrs);
}
public ObservableWebView(final Context context, final AttributeSet attrs, final int defStyle)
{
super(context, attrs, defStyle);
}
#Override
protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt)
{
super.onScrollChanged(l, t, oldl, oldt);
if(mOnScrollChangedCallback != null) mOnScrollChangedCallback.onScroll(l, t);
}
public OnScrollChangedCallback getOnScrollChangedCallback()
{
return mOnScrollChangedCallback;
}
public void setOnScrollChangedCallback(final OnScrollChangedCallback onScrollChangedCallback)
{
mOnScrollChangedCallback = onScrollChangedCallback;
}
/**
* Impliment in the activity/fragment/view that you want to listen to the webview
*/
public static interface OnScrollChangedCallback
{
public void onScroll(int l, int t);
}
}
happy coding.
I have a custom WebView with the following code:
public class ObservableWebView extends WebView {
private OnScrollChangedCallback mOnScrollChangedCallback;
public ObservableWebView(final Context context) {
super(context);
}
public ObservableWebView(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public ObservableWebView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (mOnScrollChangedCallback != null) mOnScrollChangedCallback.onScroll(l, t);
}
public OnScrollChangedCallback getOnScrollChangedCallback() {
return mOnScrollChangedCallback;
}
public void setOnScrollChangedCallback(final OnScrollChangedCallback onScrollChangedCallback) {
mOnScrollChangedCallback = onScrollChangedCallback;
}
/**
* Implement in the activity/fragment/view that you want to listen to the webview
*/
public static interface OnScrollChangedCallback {
public void onScroll(int l, int t);
}
}
I use the following method to detect whether scroll has reached the end:
#Override
public void onScroll(int l, int t) {
int tek = (int) Math.floor(webView.getContentHeight() * webView.getScale());
if(tek - webView.getScrollY() == webView.getHeight())
Toast.makeText(getActivity(), "End", Toast.LENGTH_SHORT).show();
}
Problem is it doesn't always work and fails sometimes. Is there are surer way of detecting the end of scroll of a webview that is backward compatible all the way to api level 16?
Can't find any information on how to create a rotating ScrollView in Android. With this I mean a ScrollView that restarts when reaching the last element.
I have started to implement my own custom ScrollView that scrolls to the beginning when reaching bottom. But there are still many corner cases that I need to take care off to make it smooth. (Have just put a few minutes on it so far)
public class CardScrollView extends ScrollView {
public CardScrollView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public CardScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CardScrollView(Context context) {
super(context);
}
#Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
View view = (View) getChildAt(getChildCount()-1);
int diff = (view.getBottom()-(getHeight()+getScrollY()));
if (diff == 0) {
scrollTo(0, -300);
}
super.onScrollChanged(l, t, oldl, oldt);
}
}
I was thinking there should be many people tried doing this before me but can find much information on google. Can anyone point me in the right direction before I spend days into developing my own view?
Turned out a ViewPager is better for my purpose. I found some example code from here.
https://github.com/acbelter/DirectionalCarousel
I have an app that I am building using Mono Droid. I am trying to make an endless scrollview so that my users can scroll to the bottom and have more items loaded. Here is the class that I am using
public class EndlessScroll : ScrollView
{
public EndlessScroll (Context context) : base (context)
{}
public EndlessScroll(Context context, IAttributeSet attrs) : base(context, attrs)
{}
public EndlessScroll(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
{}
public interface OnScrollViewListener
{
void onScrollChanged(EndlessScroll v, int l, int t, int oldl, int oldt);
}
public OnScrollViewListener mOnScrollViewListener;
public void setOnScrollViewListener(OnScrollViewListener l)
{
this.mOnScrollViewListener = l;
}
protected void onScrollChanged(int l, int t, int oldl, int oldt)
{
mOnScrollViewListener.onScrollChanged(this, l, t, oldl, oldt);
base.OnScrollChanged(l, t, oldl, oldt);
}
}
Here is my xml file. I converted all this code from Java so there may be something that I am doing wrong.
<com.BirdsIView.BirdsIView.EndlessScroll
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="90"
android:id="#+id/scrollView">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/viewDebug" />
</com.BirdsIView.BirdsIView.EndlessScroll>
Here is my error log
Android.Views.InflateException: Binary XML file line #1: Error inflating class com.BirdsIView.BirdsIView.EndlessScroll
at at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <IL 0x00011, 0x00068>
at Android.Runtime.JNIE nv.CallNonvirtualVoidMethod (intptr,intptr,intptr,Android.Runtime.JValue[]) [0x00084] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.18-series/3b7ef0a7/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:896
at BirdsIView.getFromParse.OnCreate (Android.OS.Bundle) [0x00016] in c:\Users\New User\Desktop\BirdsIView\BirdsIView\BirdsIView\getFromParse.cs:40
at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) [0x00011] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.18-series/3b7ef0a7/source/monodroid/src/Mono.Android/platforms/android-19/src/generated/Android.App.Activity.cs:2179
at at (wrapper dynamic-method) object.06c20e74-6eec-438c-a399-394abf9bcd74 (intptr,intptr,intptr)
at --- End of managed exception stack trace ---
at android.view.InflateException: Binary XML file line #1: Error inflating class com.BirdsIView.BirdsIView.EndlessScroll
at at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:687)
I got this to work. Apparently you need to name the xml like so
<BirdsIView.EndlessScroll
instead of
<com.BirdsIView.BirdsIView.EndlessScroll
Just need to change these functions simple
public EndlessScroll (Context context)
{
super(context);
init();
}
public EndlessScroll(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
public EndlessScroll(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
I am trying to listen to the event when the HorizontalScrollView is scrolled. Tried this but it does not print anything.
HorizontalScrollView headerScrollView = new HorizontalScrollView(this);
headerScrollView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
Log.i("hv1",event.toString());
Log.i("hv1","HELLO");
return false;
}
});
The actual problem is, I want to scroll two HorizontalScrollView at a time..ie; both of them need to scroll simultaneously when atleast one of them scrolled.
any workaround?
I used the answer below and then tried implementing this but I am not sure how I need to use the methods in the class.
TestHorizontalScrollView headerScrollView = (TestHorizontalScrollView) findViewById(R.id.headerHv);
Is this the way I need to point to the hsv element in the layout file?
You may want to try creating your own custom class that extends HorizontalScrollView and overriding the onScrollChanged() function as such
public class TestHorizontalScrollView extends HorizontalScrollView {
public TestHorizontalScrollView(Context context) {
super(context);
}
#Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
// TODO Auto-generated method stub
Log.i("Scrolling", "X from ["+oldl+"] to ["+l+"]");
super.onScrollChanged(l, t, oldl, oldt);
}
}
This overriden function will catch all changes to the scroll position even when the view is not being touched. This should keep your scroll views in sync.
old question, but maybe helpful. You can do something like this:
scrollOne = (HorizontalScrollView)findViewById(R.id.horizontal_one);
scrollTwo = (HorizontalScrollView)findViewById(R.id.horizontal_two);
scrollTwo.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View view, MotionEvent event) {
// TODO Auto-generated method stub
int scrollX = view.getScrollX();
int scrollY = view.getScrollY();
scrollOne.scrollTo(scrollX, scrollY);
return false;
}
});
ScrollView with Listener, api < 23
write below in your code
MyHorizontalScrollView scrollView = (MyHorizontalScrollView)view.findViewById(R.id.scrollViewBrowse);
scrollView.setOnScrollChangedListener(new MyHorizontalScrollView.OnScrollChangedListener() {
#Override
public void onScrollChanged(int l, int t, int oldl, int oldt) {
}
});
MyHorizontalScrollView
public class MyHorizontalScrollView extends ScrollView {
public OnScrollChangedListener mOnScrollChangedListener;
public MyHorizontalScrollView(Context context) {
super(context);
}
public MyHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (mOnScrollChangedListener != null) {
mOnScrollChangedListener.onScrollChanged(l, t, oldl, oldt);
}
}
public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener){
this.mOnScrollChangedListener = onScrollChangedListener;
}
public interface OnScrollChangedListener{
void onScrollChanged(int l, int t, int oldl, int oldt);
}
}
* Xml file *
<MyHorizontalScrollView
android:id="#+id/scrollViewBrowse"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="#drawable/backgroung"
android:padding="10dp">
</MyHorizontalScrollView>
To Avoid the the Api Level Problem... follow this.
scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
int scrollY = scrollView.getScrollY();
int scrollX = scrollView.getScrollX();
if (scrollY > 500) {
} else {
}
}
});
you can try this, i've tried so many ways, but none of them meet my needs, and then i tried to do it myself, and i succeed , and it seems good , it's smooth.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.szl.fundlistdemo.WrapContentListView
android:id="#+id/left_lv"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:scrollbars="none"/>
<HorizontalScrollView
android:id="#+id/hscrollview"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.szl.fundlistdemo.WrapContentListView
android:id="#+id/right_lv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</HorizontalScrollView>
</LinearLayout>
</ScrollView>
public class WrapContentListView extends ListView{
public WrapContentListView(Context context) {
super(context);
}
public WrapContentListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WrapContentListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
Based #Dipak's answer In kotlin:
binding.scrollList.viewTreeObserver.addOnScrollChangedListener {
val X = binding.scrollList.scrollX
val Y = binding.scrollList.scrollY
}