2016-06-03 23 views
5

Có thể liên kết một trình xử lý cho setOnPageChangeListener với một ViewPager trong tệp XML với chức năng Ràng buộc Android không?Android Event Listener Data Binding cho ViewPager

Trình diễn hiển thị các sự kiện trên Click nhưng tôi tò mò về mức độ chức năng của sự kiện mà tôi có thể triển khai với nó. Bất kỳ liên kết nào về khả năng của Ràng buộc dữ liệu cũng sẽ rất tuyệt vời. Cảm ơn.

Giả định Ví dụ:

example_activity.xml

<?xml version="1.0" encoding="utf-8"?> 
<layout xmlns:android="http://schemas.android.com/apk/res/android"> 

<data> 
    <variable name="handlers" type="com.example.Handlers"/> 
</data> 

<android.support.v4.view.ViewPager 
    android:id="@+id/pager" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 

    android:onPageChangeListener="@{handlers.pageChanged}" /> 
</layout> 

Handler.java

package com.example.viewmodels; 

import android.view.View; 

public class Handlers { 
    public void pageChanged(View view){} 
} 

Các lỗi biên dịch là:

Lỗi: (6 2) Không tìm thấy mã định danh tài nguyên cho thuộc tính 'onPageChangeListener' trong gói 'android'

Trả lời

7

Có thể thực hiện việc này. Bạn cần phải thực hiện một bộ điều hợp ràng buộc tùy chỉnh vì không có các lớp BindingAdapter được xác định trước cho các lớp Xem từ các thư viện hỗ trợ Android.

Để biết cách triển khai bộ điều hợp tùy chỉnh, bạn có thể đọc this.

Mã nên được một cái gì đó giống như dưới đây, tôi đã không kiểm tra chúng kỹ lưỡng:

<android.support.v4.view.ViewPager 
    android:id="@+id/pager" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    app:onPageChangeListener="@{handlers}" /> 

đang BindingAapter của bạn:

@BindingAdapter("onPageChangeListener") 
public static void setOnPageChangeListener(ViewPager viewPager, ViewPager.OnPageChangeListener listener) { 
    Log.i("setOnPageChangeListener"); 

    // clear listeners first avoid adding duplicate listener upon calling notify update related code 
    viewPager.clearOnPageChangeListeners(); 
    viewPager.addOnPageChangeListener(listener); 
} 

T.B. Lớp trình xử lý của bạn đang được thông qua sẽ triển khai ViewPager.OnPageChangeListener.

+1

Giải pháp không tốt. Bởi vì ViewPager thêm OnPageChangeListener vào ArrayList nội bộ, gọi notifyChange() cho thuộc tính này sẽ làm cho nó thêm một vài người nghe. Đã cập nhật – b1n0m

+0

@ b1n0m để xóa người nghe trước khi thêm người nghe –

3

Đây là giải pháp tối thượng. Chỉ cần đặt lớp này trong dự án của bạn.

@BindingMethods({ 
    @BindingMethod(type = ViewPager.class, attribute = "android:offscreenPageLimit", method = "setOffscreenPageLimit"), 
    @BindingMethod(type = ViewPager.class, attribute = "android:adapter", method = "setAdapter"), 
    @BindingMethod(type = ViewPager.class, attribute = "android:currentPage", method = "setCurrentItem"), 
}) 
public final class ViewPagerBindingAdapter { 

    @InverseBindingAdapter(attribute = "android:currentPage", event = "android:currentPageAttrChanged") 
    public static int getCurrentPage(@NonNull final ViewPager pager) { 
     return pager.getCurrentItem(); 
    } 

    @BindingAdapter(value = {"android:onPageScrolled", "android:onPageSelected", "android:onPageScrollStateChanged", 
     "android:currentPageAttrChanged"}, requireAll = false) 
    public static void onSetAdapter(@NonNull final ViewPager pager, final OnPageScrolled scrolled, final OnPageSelected selected, 
     final OnPageScrollStateChanged scrollStateChanged, final InverseBindingListener currentPageAttrChanged) { 

     final ViewPager.OnPageChangeListener newValue; 
     if (scrolled == null && selected == null && scrollStateChanged == null && currentPageAttrChanged == null) { 
      newValue = null; 
     } else { 
      newValue = new ViewPager.OnPageChangeListener() { 
       @Override 
       public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) { 
        if (scrolled != null) { 
         scrolled.onPageScrolled(position, positionOffset, positionOffsetPixels); 
        } 
       } 

       @Override 
       public void onPageSelected(final int position) { 
        if (selected != null) { 
         selected.onPageSelected(position); 
        } 
        if (currentPageAttrChanged != null) { 
         currentPageAttrChanged.onChange(); 
        } 
       } 

       @Override 
       public void onPageScrollStateChanged(final int state) { 
        if (scrollStateChanged != null) { 
         scrollStateChanged.onPageScrollStateChanged(state); 
        } 
       } 
      }; 
     } 
     final ViewPager.OnPageChangeListener oldValue = ListenerUtil.trackListener(pager, newValue, R.id.page_change_listener); 
     if (oldValue != null) { 
      pager.removeOnPageChangeListener(oldValue); 
     } 
     if (newValue != null) { 
      pager.addOnPageChangeListener(newValue); 
     } 
    } 

    public interface OnPageScrolled { 
     void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); 
    } 

    public interface OnPageSelected { 
     void onPageSelected(int position); 
    } 

    public interface OnPageScrollStateChanged { 
     void onPageScrollStateChanged(int state); 
    } 

    private ViewPagerBindingAdapter() { 
     throw new UnsupportedOperationException(); 
    } 
} 

Đồng thời thêm tài nguyên id vào tài nguyên của bạn.

<resources> 
    <item name="page_change_listener" type="id"/> 
</resources> 

Sau đó, bạn sẽ có thể sử dụng nó trong xml như:

<android.support.v4.view.ViewPager 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:currentPage="@={viewModel.currentPage}" 
       android:offscreenPageLimit="@{viewModel.offscreenPageLimit}" 
       android:onPageSelected="@{currentPage -> viewModel.pageSelected(currentPage)}" 
       android:adapter="@{adapter}"/> 

Như bạn thấy, currentPage đã nghịch đảo ràng buộc, vì vậy ViewModel của bạn sẽ có thể thiết lập trang hiện tại và cũng có được hiện tại trang nếu người dùng vuốt.

+0

những cài đặt này có thể cập nhật phân đoạn động trong chế độ xem động không? trong thời gian thực? –

+0

@ azizi-musa, bạn có thể đặt giá trị 'viewModel.currentPage' để chọn một trang khác. Nếu bạn muốn thay đổi các mảnh trong 'ViewPager', bạn nên làm điều này trong' PagerAdapter'. – b1n0m

Các vấn đề liên quan