OnScrollChanged не получает параметры RecyclerView

Я пытаюсь реализовать этот код здесь, в моем проекте: https://startupriteofpassage.wordpress.com/2014/09/04/android-fading-action-bar-in-xamarin-c/

Различия в том, что вместо ScrollView я использую RecyclerView и что вместо того, чтобы мой RecyclerView находился непосредственно в "Деятельности", внутри фрагмента, который устанавливает нужного слушателя. Проблема в том, что хотя OnScrollChanged (int l, int t, int oldl, int oldt) фактически вызывается при каждой прокрутке, параметры, которые он получает, всегда равны 0, и я не понимаю, почему, поэтому ScrollChangedTarget не работает должным образом,

Это пользовательский RecyclerView:

 public class NotifyingScrollRecyclerView : RecyclerView
{
    private Activity activity;
    private View headerView;
    private View footerView;

    public delegate void ScrollChangedHandler(int l, int t, int oldl, int oldt, EventArgs e);

    public event ScrollChangedHandler scrollChanged;
    public EventArgs e = null;

    //Enabling all required constructors
    public NotifyingScrollRecyclerView(Context context) : base(context)
    {

    }

    public NotifyingScrollRecyclerView(Context context, IAttributeSet attrs) : base(context, attrs)
    {

    }

    public NotifyingScrollRecyclerView(IntPtr ptr, JniHandleOwnership ownership) : base(ptr, ownership)
    {

    }

    public NotifyingScrollRecyclerView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
    {

    }

    //This method attribute allows us to register the inbuilt OnScrollChanged event that fires when scrolling a ScrollView
    [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);
        scrollChanged(l, t, oldl, oldt, e);
    }



}


//Set an event listener
public class ScrollViewChangedListener
{
    private Activity activity;
    private NotifyingScrollRecyclerView scrollView;
    private Android.Support.V7.App.ActionBar actionBar;
    private Drawable actionBarDrawable;
  be changed
    public ScrollViewChangedListener(Activity a, NotifyingScrollRecyclerView n)
    {
        n.scrollChanged += ScrollChangedTarget;
        this.activity = a;
        this.scrollView = n;
        this.actionBar = ((UserPageActivity)a).SupportActionBar;

        this.actionBarDrawable = a.GetDrawable(Resource.Drawable.actionbar_background);
        this.actionBarDrawable.SetAlpha(0);

    }

    //Handle the changing of the scroll
    public void ScrollChangedTarget(int l, int t, int oldl, int oldt, EventArgs e)
    {
        //You set the View you want to be your header as a header height, and then get it's height
        int headerHeight = activity.FindViewById<ImageView>(Resource.Id.profilebanner).Height -
        this.actionBar.Height;
        float ratio = (float)Math.Min(Math.Max(t, 0), headerHeight) / headerHeight;
        int newAlpha = (int)(ratio * 255);

            this.actionBarDrawable.SetAlpha(newAlpha);
            this.actionBar.SetBackgroundDrawable(this.actionBarDrawable);


    }

}

Это Activity, которая вызывает фрагмент (в этом случае он ничего не делает, кроме вызова фрагмента):

[Activity(Label = "UserPageActivity")]
public class UserPageActivity : BaseActivity
{
    protected override int LayoutResource => Resource.Layout.activity_user_page;
    UserViewModel viewModel;
    TextView username;
    TextView usernameToolbar;
    Button followButton;


    ViewPager pager;
    UserTabsAdapter adapter;
    bool IsLoggedUser;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        IsLoggedUser = Intent.GetStringExtra("userId").Equals(LoginController.GetInstance().CurrentUser.Email);
        base.OnCreate(savedInstanceState);
        viewModel = new UserViewModel();
        viewModel.UserLoaded += new UserViewModel.UserLoadedHandler(OnUserLoaded);
        viewModel.LoadUserCommand.Execute(Intent.GetStringExtra("userId"));
        username = FindViewById<TextView>(Resource.Id.profilename);
        usernameToolbar = FindViewById<TextView>(Resource.Id.usernamePage);
        followButton = FindViewById<Button>(Resource.Id.followButton);

        username.Text = Intent.GetStringExtra("username");
        usernameToolbar.Text = Intent.GetStringExtra("username");

        adapter = new UserTabsAdapter(this, SupportFragmentManager);
        pager = FindViewById<ViewPager>(Resource.Id.user_viewpager);
        var tabs = FindViewById<TabLayout>(Resource.Id.tabs);
        pager.Adapter = adapter;
        tabs.SetupWithViewPager(pager);
        pager.OffscreenPageLimit = 5;


        pager.PageSelected += (sender, args) =>
        {
            var fragment = adapter.InstantiateItem(pager, args.Position) as IFragmentVisible;

            fragment?.BecameVisible();
        };
    }

    private void OnUserLoaded(bool loaded)
    {

    }

    protected override void OnStart()
    {
        base.OnStart();

        if (IsLoggedUser)
        {
            followButton.Visibility = ViewStates.Gone;

        }
        else
        {
            bool following;
            if (LoginController.GetInstance().CurrentUser.FollowsUsers.ContainsKey(Intent.GetStringExtra("userId")))
            {
                followButton.Text = "Unfollow";
                following = true;
            }
            else
            {
                followButton.Text = "Follow";
                following = false;
            }

            followButton.Click += (object sender, EventArgs e) =>
            {
                followButton.Enabled = false;
                if (following)
                {
                    UserService service = ServiceLocator.Instance.Get<UserService>();

                    service.SetUser(LoginController.GetInstance().CurrentUser);
                    service.RemoveFollowsUserCommand.Execute(viewModel.LoadedUser.Email);

                    service.SetUser(viewModel.LoadedUser);
                    service.RemoveFollowedByUserCommand.Execute(LoginController.GetInstance().CurrentUser.Email);

                    followButton.Text = "Follow";
                    following = false;
                }
                else
                {
                    UserService service = ServiceLocator.Instance.Get<UserService>();

                    service.SetUser(LoginController.GetInstance().CurrentUser);
                    service.AddFollowsUserCommand.Execute(viewModel.LoadedUser);

                    service.SetUser(viewModel.LoadedUser);
                    service.AddFollowedByUserCommand.Execute(LoginController.GetInstance().CurrentUser);

                    followButton.Text = "Unfollow";
                    following = true;
                }
                followButton.Enabled = true;
            };
        }
    }
}

class UserTabsAdapter : FragmentStatePagerAdapter
{
    string[] titles;

    public override int Count => titles.Length;

    public UserTabsAdapter(Context context, Android.Support.V4.App.FragmentManager fm) : base(fm)
    {
        titles = context.Resources.GetTextArray(Resource.Array.user_sections);
    }

    public override Java.Lang.ICharSequence GetPageTitleFormatted(int position) =>
                        new Java.Lang.String(titles[position]);

    public override Android.Support.V4.App.Fragment GetItem(int position)
    {
        switch (position)
        {
            case 0: return UserContestsFragment.NewInstance();
            case 1: return UserPartecipationsFragment.NewInstance();
            case 2: return GlobalContestFragment.NewInstance();
            case 3: return MessagesFragment.NewInstance();
        }
        return null;
    }

    public override int GetItemPosition(Java.Lang.Object frag) => PositionNone;
}

Это фрагмент, который настраивает слушателя для просмотра реселлера:

      public class UserContestsFragment : AbstractRefresherFadingToolbarFragment<Contest>
{
    public static UserContestsFragment NewInstance() =>
        new UserContestsFragment { Arguments = new Bundle() };


    public override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
    }

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        ContestViewModel viewModel = new ContestViewModel();
        base.ViewModel = viewModel;
        base.LoadItemsCommand = viewModel.LoadAllByCreatorUserCommand;
        base.param = Activity.Intent.GetStringExtra("userId");
        base.adapter = new ContestsAdapter(Activity, viewModel);
        var view = base.OnCreateView(inflater, container, savedInstanceState);

        ScrollViewChangedListener listener = new ScrollViewChangedListener(Activity, recyclerView);
        return view;
    }

И это абстрактный фрагмент, необходимый для того фрагмента, который отвечает за настройку макета:

  public abstract class AbstractRefresherFadingToolbarFragment<T> : Android.Support.V4.App.Fragment, IFragmentVisible
{
    public ICollectionViewModel<T> ViewModel;
    public ICommand LoadItemsCommand;
    public object param; //parametro per il LoadItemsCommand
    public ItemsAdapter<T> adapter;
    public SwipeRefreshLayout refresher;
    public ProgressBar progress;
    public NotifyingScrollRecyclerView recyclerView;
    //LruCache cache = new LruCache((int)(Runtime.GetRuntime().MaxMemory() / 4));

    public override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
    }

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View view = inflater.Inflate(Resource.Layout.fragment_fading_toolbar, container, false);
        recyclerView = view.FindViewById<NotifyingScrollRecyclerView>(Resource.Id.recyclerView);
        //ScrollViewChangedListener listener = new ScrollViewChangedListener((UserPageActivity)Activity, recyclerView);
        //adapter.cache = cache;
        recyclerView.HasFixedSize = true;
        recyclerView.SetAdapter(adapter);
        recyclerView.SetItemViewCacheSize(4);
        //recyclerView.ChildViewAttachedToWindow += new EventHandler<RecyclerView.ChildViewAttachedToWindowEventArgs>(OnChildViewAttached);
        //recyclerView.ChildViewDetachedFromWindow += new EventHandler<RecyclerView.ChildViewDetachedFromWindowEventArgs>(OnChildViewDetached);

        refresher = view.FindViewById<SwipeRefreshLayout>(Resource.Id.refresher);
        refresher.SetColorSchemeColors(Resource.Color.accent);

        progress = view.FindViewById<ProgressBar>(Resource.Id.progressbar_loading);
        progress.Visibility = ViewStates.Gone;

        return view;
    }


}

1 ответ

Решение

Я не прочитал весь ваш код, но посмотрел сайт, на который вы ссылались в вашем вопросе. Функциональность скрытой панели действий, которую вы хотите использовать, обрабатывается CollapsingToolbarLayout в библиотеке поддержки. Чтобы узнать, как его использовать, перейдите на Cheesesquare. Это полный пример виджетов библиотеки поддержки и может быть собран и запущен без каких-либо изменений.

Изменить: RecyclerView имеет метод с именем AddOnScrollListener. Используйте его вместо OnScrollChanged. Если вы используете унаследованный класс от RecyclerView, вы можете вызывать его во всех конструкторах этого класса.

Другие вопросы по тегам