将相关视图捆绑到窗口小部件并为其提供数据

时间:2016-05-26 17:02:55

标签: android

我有一个像这样的xml文件

    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:id="@+id/book_dialog_btn"
            android:src="@drawable/book"
            android:onClick="showDialog"/>

        <EditText
            android:id="@+id/code_field"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="number" />

    </LinearLayout>

EditText字段必须填充一个产品ID的整数,用户可以通过两种方式输入

  • 用户可以点击图片按钮打开包含列表的对话框,在用户选择项目后,id将被插入到edittext
  • 用户知道产品ID并手动输入

这些xml代码在多个活动中重复,因此我将其捆绑到这样的自定义视图中

public class PiceBookCodeField extends LinearLayout{

   public PiceBookCodeField (Context context, AttributeSet attr, int defStyle) {
       super(context, attr, defStyle);
       init();
   }

   public PiceBookCodeField (Context context, AttributeSet attr) {
       super(context, attr);
       init();
   }

   public PiceBookCodeField (Context context) {
       super(context);
       init();
   } 

   private void init() {

    LinearLayout root = (LinearLayout) inflate(getContext(), R.layout.price_book_code_field, this);

   } 
}

我在xml中使用下面的代码

<com.sth.PiceBookCodeField 
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

但我不知道如何管理与it相关的逻辑。我想将textwatcher添加到edittext以及当用户输入代码搜索数据库以检查数据库中是否存在代码时。 但我读到某个地方,我们不能把数据相关的逻辑放在视野中,但我应该写那些逻辑并避免重复它

2 个答案:

答案 0 :(得分:0)

添加textwatcher并在其中启动异步任务。

数据搜索,加载,下载等都必须处于异步任务中。制作异步任务以执行搜索并在其上onPostExecute - 根据您获得的结果更改文本视图)

答案 1 :(得分:0)

通常,您将获得对子视图的引用,之后您可以进一步配置它们(例如设置OnClickListener s或TextWatcher s)。您还可以在视图上创建公共方法,该方法委托其子项上的方法来支持您想要的行为。

public class PiceBookCodeField extends LinearLayout {
    private ImageView mImageView;
    private EditText mEditText;

    /* constructors omitted */

    private void init() {
        LayoutInflater inflater = LayoutInflater.from(getContext());
        inflater.inflate(R.layout.price_book_code_field, this, true);

        mImageView = (ImageView) findViewById(R.id.book_dialog_btn);
        mEditText = (EditText) findViewById(R.id.code_field);

        // TODO stuff
    }

    // example method
    public void setCode(String code) {
        mEditText.setText(code);
    }
}

可能有意义的是为自定义视图支持的各种操作创建自己的interface。然后在你的init()方法中,设置你通常会听到的任何监听器,但让它们调用你的监听器接口。然后,您的视图的任何用户都可以设置一个监听器,以便在适当的时候采取措施:

public interface CodeFieldListener {
    void onCodeBookClick(PiceBookCodeField view);
    void onCodeEntered(PiceBookCodeField view, String code);
}

private CodeFieldListener mCodeFieldListener;

public void setCodeFieldListener(CodeFieldListener listener) {
    mCodeFieldListener = listener;
}

// inside of init()
mImageView.setOnClickListener(v -> {
    if (mCodeFieldListener != null) {
        mCodeFieldListener.onCodeBookClick(this);
    }
}); 

请注意,由于您的自定义视图已经是LinearLayout,因此子项的XML可以使用<merge>标记作为根而不是<LinearLayout>

<merge>
    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:id="@+id/book_dialog_btn"
        android:src="@drawable/book" />

    <EditText
        android:id="@+id/code_field"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="number" />
</merge>

这样,自定义视图的最终层次结构为

PiceBookCodeField
    ImageView
    EditText

而不是

PiceBookCodeField
    LinearLayout
        ImageView
        EditText