
Android
现在讨论的是自定义复合视图。视图由多个其他的视图组成,内置的或自定义的都可以,用来封装复杂的交互和功能。
在一个成熟且完整的Fragment完全满足我需求的情况下,我使用了复合视图,因为我想要一个可重用、可测试的组件。上面的例子很好的说明了这种情况。由于代码属于一个客户项目,所以我在这里创建了一个简单的项目展示如何创建和使用自定义视图。

etc
在本例中,我们希望自定义视图添加编辑框,这样用户就可以输入任意数量的数据条目。在自定义视图中,可以通过使用一个包含了适当数量编辑框的简单容器视图(线性布局)实现,因而可以很容易地获取名称列表。代码如下:
/ * A custom compound view that displays an arbitrary * number of text views to enter your friends names. */ public class FriendNameView extends LinearLayout {
private int mFriendCount; private int mEditTextResId;
public FriendNameView(Context context) { this(context, null); }
public FriendNameView(Context context, AttributeSet attrs) { this(context, attrs, 0); }
public FriendNameView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setOrientation(VERTICAL); }
public int getFriendCount() { return mFriendCount; }
public void setFriendCount(int friendCount) { if (friendCount != mFriendCount) { mFriendCount = friendCount;
removeAllViews(); for (int i = 0; i mFriendCount; i++) { addView(createEditText()); } } }
private View createEditText() { View v; if (mEditTextResId 0) { LayoutInflater inflater = LayoutInflater.from(getcontext()); v = inflater.inflate(mEditTextResId, this, true); } else { EditText et = new EditText(getcontext()); et.setHint(R.string.friend_name); v = et; } return v; }
public int getEditTextResId() { return mEditTextResId; }
public void setEditTextResId(int editTextResId) { mEditTextResId = editTextResId; }
/ * Returns a list of entered friend names. */ public ListgetFriendNames() { List names = new ArrayList(); for (int i = 0; i getchildCount(); i++) { View v = getchildAt(i); if (v instanceof EditText) { EditText et = (EditText) v; names.add(et.getText().toString()); } } return names; } } 当用户使用 setFriendCount(int) 方法设置朋友的数量时,我们重置基于输入的子编辑框字段数目。这里使用一个自定义布局的完成,但是将默认为一个简单的编辑框。 当我们要获取用户已经输入的名称列表时,可以不必关心自定义视图的内部结构。只需调用 getFriendNames()方法,视图就会汇集名称列表。 这就是这个简单的例子。作为一种特殊的副作用,因为这个视图只是由一个线性布局(父类)和编辑框视图组成,它们已经知道如何保存和恢复状态,所以无需对状态进行处理。 布局中包含自定义视图 当想要在Activity或Fragment布局中使用自定义视图时,可以像使用其它的视图一样,加入一些简单的XML。 Android:id="@+id/friend_names" Android:layout_width="match_parent" Android:layout_height="wrap_content"/ 和其它的视图一样,可以使用 findViewById(int)方法来得到它。 1 mFriendNameView = (FriendNameView) findViewById(R.id.friend_names); 在我们的MAInActivity中,当数据拾取器的值变化时,我们可以非常容易地设置朋友的数量。当想要获取名称列表时,调用getFriendNames()方法。 mFriendCountPicker.setOnValueChangedListener(new OnValueChangeListener() { @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { mFriendNameView.setFriendCount(newVal); } }); mCountFriendsButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { List names = mFriendNameView.getFriendNames(); Intent i = new Intent(MAInActivity.this, FriendCountActivity.class); i.putStringArrayListExtra("names", new ArrayList(names)); startActivity(i); } }); 尽管这是一个刻意设计的例子,但是自定义复合视图是一个极好功能封装方式。如果不进行封装,功能代码将散落在整个活动和片段中。自定义复合视图提供了可测试、可重用的代码,让应用程序更稳定。我鼓励大家想一想,自己的应用程序中哪里可以使用自定义复合视图。如果可以的话并与其他开发者分享,它们是非常有用的。 转载
Copyright © 2025 IZhiDa.com All Rights Reserved.
知答 版权所有 粤ICP备2023042255号