[英]How can I include a custom view in an existing XML layout on Android?
[英]Android: Multiple view children for custom view with existing layout
我必须在 Android 中构建更复杂的自定义视图。 最终布局应如下所示:
<RelativeLayout>
<SomeView />
<SomeOtherView />
<!-- maybe more layout stuff here later -->
<LinearLayout>
<!-- the children -->
</LinearLayout>
</RelativeLayout>
但是,在 XML 文件中我只想定义它(不定义 SomeView、SomeOtherView 等):
<MyCustomView>
<!-- the children -->
</MyCustomView>
这在 Android 中是否可行,如果是:最干净的方法是什么? 我想到的可能解决方案是“覆盖 addView() 方法”和“删除所有视图并稍后再次添加它们”,但我不确定该走哪条路......
非常感谢您的帮助::)
创建自定义容器视图是完全可能的,并且受到鼓励。 这就是 Android 所说的复合控件。 所以:
public class MyCustomView extends RelativeLayout {
private LinearLayout mContentView;
public MyCustomView(Context context) {
this(context, null);
}
public MyCustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//Inflate and attach your child XML
LayoutInflater.from(context).inflate(R.layout.custom_layout, this);
//Get a reference to the layout where you want children to be placed
mContentView = (LinearLayout) findViewById(R.id.content);
//Do any more custom init you would like to access children and do setup
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if(mContentView == null){
super.addView(child, index, params);
} else {
//Forward these calls to the content view
mContentView.addView(child, index, params);
}
}
}
您可以根据需要覆盖任意多个版本的addView()
,但最终它们都会回调到我放置在示例中的版本。 仅覆盖此方法将使框架将在其 XML 标记内找到的所有子项传递给特定的子容器。
然后这样修改 XML:
资源/布局/custom_layout.xml
<merge>
<SomeView />
<SomeOtherView />
<!-- maybe more layout stuff here later -->
<LinearLayout
android:id="@+id/content" />
</merge>
使用<merge>
的原因是为了简化层次结构。 所有子视图都将附加到您的自定义类,即RelativeLayout
。 如果您不使用<merge>
,您最终会将一个RelativeLayout
附加到另一个附加到所有子项的RelativeLayout
,这可能会导致问题。
private fun expand(view: View) {
val parentWidth = (view.parent as View).width
val matchParentMeasureSpec = MeasureSpec.makeMeasureSpec(parentWidth, MeasureSpec.EXACTLY)
val wrapContentMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
view.measure(matchParentMeasureSpec, wrapContentMeasureSpec)
val targetHeight = view.measuredHeight
view.isVisible = true
val animation: Animation = getExpandAnimation(view, targetHeight)
view.startAnimation(animation)
}
private fun getExpandAnimation(
view: View,
targetHeight: Int
): Animation = object : Animation() {
override fun applyTransformation(
interpolatedTime: Float,
transformation: Transformation
) {
view.layoutParams.height =
if (interpolatedTime == 1f) {
LayoutParams.WRAP_CONTENT
} else {
(targetHeight * interpolatedTime).toInt()
}
view.requestLayout()
}
override fun willChangeBounds(): Boolean {
return true
}
}.apply {
duration = getDuration(targetHeight, view)
}
private fun collapse(view: View) {
val initialHeight = view.measuredHeight
val animation: Animation = getCollapseAnimation(view, initialHeight)
view.startAnimation(animation)
}
private fun getCollapseAnimation(
view: View,
initialHeight: Int
): Animation = object : Animation() {
override fun applyTransformation(
interpolatedTime: Float,
transformation: Transformation
) {
if (interpolatedTime == 1f) {
view.isVisible = false
} else {
view.layoutParams.height =
initialHeight - (initialHeight * interpolatedTime).toInt()
view.requestLayout()
}
}
override fun willChangeBounds(): Boolean = true
}.apply {
duration = getDuration(initialHeight, view)
}
/**
* Speed = 1dp/ms
*/
private fun getDuration(initialHeight: Int, view: View) =
(initialHeight / view.context.resources.displayMetrics.density).toLong()
你可以使用include标签
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
<include android:id="@+id/nav_bar_layout" layout="@layout/nav_bar" android:layout_above="@+id/web_view" />
<WebView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/web_view" android:layout_centerInParent="true" />
<include android:id="@+id/admob_layout" layout="@layout/admob_layout" android:layout_below="@+id/web_view" />
</RelativeLayout>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.