Android 复合视图不接受来自 xml 的 onclick

In Android compound view is not accepting onclick from xml

我开发了一个自定义复合视图,其中有一个 Button 和一个 ProgressBar。我在我的应用程序中使用 databinding。复合视图不接受 onClick 事件,如何解决这个问题?

<com.ui.custom.LoadingButton
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/bg_color"
            android:onClick="@{()->viewModel.onNextClick()}"
            android:text="@string/next"
            android:textColor="@color/white"
            app:isLoading="@{viewModel.isLoading}" />

加载按钮布局:

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

    <data>

    </data>

    <FrameLayout
        android:id="@+id/parentFrame"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?android:selectableItemBackground"
            android:textSize="@dimen/btn_text_size" />

        <com.wang.avi.AVLoadingIndicatorView
            android:id="@+id/loading_indicator"
            android:layout_width="@dimen/btn_loading_indicator"
            android:layout_height="@dimen/btn_loading_indicator"
            android:layout_gravity="center"
            android:elevation="@dimen/cardview_default_elevation"
            app:indicatorName="LineSpinFadeLoaderIndicator" />
    </FrameLayout>
</layout>

或者如果我使用 android 的 'onClick' 属性,那么如何在 TypedArray 中获取它?所以我可以将它设置为以编程方式查看。

   <declare-styleable name="LoadingButton">
        <attr name="isLoading" format="boolean" />
        <attr name="android:text" />
        <attr name="android:textColor" />
        <attr name="android:background" />
        <attr name="android:onClick" />

    </declare-styleable>

加载按钮java

@BindingMethods({
        @BindingMethod(type = LoadingButton.class, attribute = "onLoadingButtonClick", method = "onLoadingButtonClick"),
})
public class LoadingButton extends LinearLayout implements View.OnClickListener {

    private Context mContext;
    private int background, textColor;
    private boolean isLoading;
    private String btnText;
    private LayoutLoadingBtnBinding itemViewBinding;
    private OnLoadingButtonListener listener;

    public LoadingButton(Context context) {
        super(context);
        initializeView(context, null, 0);
    }

    public LoadingButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        initializeView(context, attrs, 0);
    }

    public LoadingButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initializeView(context, attrs, defStyleAttr);
    }

    private void initializeView(Context context, AttributeSet attrs, int defStyleAttr) {
        mContext = context;
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.LoadingButton, defStyleAttr, 0);

        try {
            background = array.getColor(R.styleable.LoadingButton_android_background, Integer.MAX_VALUE);
            textColor = array.getColor(R.styleable.LoadingButton_android_textColor, Integer.MAX_VALUE);
            btnText = array.getString(R.styleable.LoadingButton_android_text);
            isLoading = array.getBoolean(R.styleable.LoadingButton_isLoading, false);
            //   Method onClick = array.getValue(R.styleable.LoadingButton_android_onClick);
        } finally {
            array.recycle();
        }

        itemViewBinding = LayoutLoadingBtnBinding.inflate(LayoutInflater.from(mContext), this, true);

    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

      //  setOnClickListener(this::onClick);
        setValues();

    }

    private void setValues() {
        try {
            if (background != Integer.MAX_VALUE)
                itemViewBinding.parentFrame.setBackgroundColor(background);

            if (background != Integer.MAX_VALUE) {
                itemViewBinding.button.setTextColor(textColor);
                itemViewBinding.loadingIndicator.setIndicatorColor(textColor);
            }
            itemViewBinding.button.setText(btnText);
            updateLoadingViews();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void updateLoadingViews() {
        itemViewBinding.button.setVisibility(isLoading ? INVISIBLE : VISIBLE);
        itemViewBinding.loadingIndicator.setVisibility(isLoading ? VISIBLE : GONE);
    }

    public void setLoading(boolean isLoading) {
        if (this.isLoading != isLoading)  // update only if loading state is changed
        {
            this.isLoading = isLoading;
            updateLoadingViews();
        }
    }

    public void setOnLoadingButtonClick(OnLoadingButtonListener listener) {
        AppLogger.d("usm_loading_btn_0", "setOnLoadingButtonClick is called: listener= " + (listener != null));
        this.listener = listener;
    }

    @Override
    public void onClick(View view) {
        AppLogger.d("usm_loading_btn_1", "onClick is called");
        if (listener != null) {
            listener.onLoadingButtonClick();
        }
    }

    public interface OnLoadingButtonListener {
        void onLoadingButtonClick();
    }

}

你不能使用这种方式

<attr name="android:onClick" />

尝试使用BindingMethods

@BindingMethods({
        @BindingMethod(type = LoadingButton.class, attribute = "onLoadingButtonClick", method = "onLoadingButtonClick"),
})
public class LoadingButton extends YOUR_ROOT_VIEW implements View.OnClickListener {
  // your item view class.
  private OnLoadingButtonListener listener;

  public void setOnLoadingButtonClick(OnLoadingButtonListener listener) {
     this.listener = listener;
  }

  @Override
  public void onClick(View view) {
    if (listener != null) {
        listener.onLoadingButtonClick();
    }
  }
  public interface OnLoadingButtonListener {
    void onLoadingButtonClick();
  }
}

并在您的布局中

<com.ui.custom.LoadingButton
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/bg_color"
            android:onLoadingButtonClick="@{()->viewModel.onNextClick()}"
            android:text="@string/next"
            android:textColor="@color/white"
            app:isLoading="@{viewModel.isLoading}" />

更新 1

如果您的 onClick() 不起作用,请将其删除并尝试使用这种方式

private void initializeView(Context context, AttributeSet attrs, int defStyleAttr) {
        mContext = context;
        TypedArray array =
                context.obtainStyledAttributes(attrs, R.styleable.LoadingButton, defStyleAttr, 0);

        try {
            background =
                    array.getColor(R.styleable.LoadingButton_android_background, Integer.MAX_VALUE);
            textColor =
                    array.getColor(R.styleable.LoadingButton_android_textColor, Integer.MAX_VALUE);
            btnText = array.getString(R.styleable.LoadingButton_android_text);
            isLoading = array.getBoolean(R.styleable.LoadingButton_isLoading, false);
            //   Method onClick = array.getValue(R.styleable.LoadingButton_android_onClick);
        } finally {
            array.recycle();
        }

        itemViewBinding =
                LayoutLoadingBtnBinding.inflate(LayoutInflater.from(mContext), this, true);
        itemViewBinding.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (listener != null) {
                    listener.onLoadingButtonClick();
                }
            }
        });
    }