创建 Android 个子视图,例如 iOS 个子视图
Create Android subviews like iOS subviews
我正在尝试编程(不使用XML文件)在Android中创建自定义子视图(这就是我在[=85中的称呼) =]) 这基本上是一些基本视图(标签、按钮、文本字段等)组合成一个可重用的子视图 class,所以我可以在我的 UIViewControllers
或 Activity
中使用它在 Android.
我不知道 Android 中的正确术语是什么。似乎有一百万种不同的术语。
自定义视图、视图组、布局、小部件、组件,随便你怎么称呼它。
在 iOS 中,可以这样简单地完成:
CustomView.h
@interface CustomView : UIView
@property (nonatomic, strong) UILabel *message;
@property (nonatomic, strong) UIButton *button;
@end
CustomView.m
@implementation CustomView
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
[self initViews];
[self initConstraints];
}
return self;
}
-(void)initViews
{
self.message = [[UILabel alloc] init];
self.button = [[UIButton alloc] init];
[self addSubview:self.message];
[self addSubview:self.button];
}
-(void)initConstraints
{
id views = @{
@"message": self.message,
@"button": self.button
};
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[message]|" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[button]|" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[message][button]|" options:0 metrics:nil views:views]];
}
@end
现在我可以在我选择的任何 ViewController (Android Activity
) 中重复使用此自定义视图。
如何在 Android 中取得这样的成就?
我一直在环顾四周,从我在 Android 中收集到的内容中添加子视图,我将它们添加到 Layouts
:
RelativeLayout relativeLayout = new RelativeLayout(...);
TextView textView = new TextView(...);
relativeLayout.addSubview(textView);
这是否意味着我需要扩展 RelativeLayout
或 ViewGroup
?
查看此页面:http://developer.android.com/reference/android/view/ViewGroup.html
看来我们需要编写一些非常复杂的逻辑来布局自定义视图,例如:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int count = getChildCount();
// These keep track of the space we are using on the left and right for
// views positioned there; we need member variables so we can also use
// these for layout later.
mLeftWidth = 0;
mRightWidth = 0;
// Measurement will ultimately be computing these values.
int maxHeight = 0;
int maxWidth = 0;
int childState = 0;
// Iterate through all children, measuring them and computing our dimensions
// from their size.
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
// Measure the child.
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
// Update our size information based on the layout params. Children
// that asked to be positioned on the left or right go in those gutters.
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.position == LayoutParams.POSITION_LEFT) {
mLeftWidth += Math.max(maxWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
} else if (lp.position == LayoutParams.POSITION_RIGHT) {
mRightWidth += Math.max(maxWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
} else {
maxWidth = Math.max(maxWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
}
maxHeight = Math.max(maxHeight,
child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
childState = combineMeasuredStates(childState, child.getMeasuredState());
}
}
// Total width is the maximum width of all inner children plus the gutters.
maxWidth += mLeftWidth + mRightWidth;
// Check against our minimum height and width
maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
// Report our final dimensions.
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
resolveSizeAndState(maxHeight, heightMeasureSpec,
childState << MEASURED_HEIGHT_STATE_SHIFT));
}
我想做的就是在自定义视图中使用多个基本 android 标签、视图、按钮,如上面的 iOS 示例,为什么在 Android ?
我希望得到像这样简单的东西:
public class CustomView extends View
{
public RelativeLayout mainLayout;
public TextView message;
public Button button;
// default constructor
public CustomView()
{
...
initViews();
initLayouts();
addViews();
}
public initViews()
{
mainLayout = new RelativeLayout(this);
message = new TextView(this);
button = new Button(this);
...
}
public initLayouts()
{
// --------------------------------------------------
// use Android layout params to position subviews
// within this custom view class
// --------------------------------------------------
}
public addViews()
{
mainLayout.addView(message);
mainLayout.addView(button);
setContentView(mainLayout);
}
}
抱歉,我是真诚地尝试学习和构建一个基本的 Android 应用程序,而不是尝试 bash Android 的做事方式。
我知道如何在 Activity 中添加和布局子视图,过去两天我一直在这样做,但在自定义 View/View Group/Layout 中却不知道。我不想最终为 Android 应用程序中的每个 Activity 构建完全相同的子视图,这违背了良好的编码习惯,对吗? :D
这里只需要一些已经完成 iOS 和 Android 开发的其他人的指导。
编辑
我要找的好像是复合控件:http://developer.android.com/guide/topics/ui/custom-components.html
我会继续挖掘,希望能达到我想要的结果:D
只需要解决这个Inflater业务。
Android 和 ios 应用程序开发是两个不同的概念,每个都有自己的方式来执行您的任务。有时 android 有时 ios 很难开发一段代码。
要在 android 中创建视图 screen/design/GUI,您可以创建 XML 文件(推荐)或通过代码(这在某种程度上难以维护 w.r.t XML)。
对于您的问题,您不需要创建自己的 ViewGroup
或 RelativeLayout
或 LinearLayout
,例如如果您想使用 RelativeLayout
作为您视图的父级而不是使用 XML 您可以使用。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some Text"/>
</RelativeLayout>
如果您想实用地创建视图而不是使用
RelativeLayout parentRelativeLayout = new RelativeLayout(context);
RelativeLayout.LayoutParams parentParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
parentRelativeLayout.setLayoutParams(parentParams);
TextView childTextView = new TextView(context);
childTextView.setText("Some Text");
mRelativeLayout.addView(childTextView);
它只是一个示例代码,两者都具有相同的输出,但是使用编程方法,随着您的视图的增长,这将变得困难。
查看您的代码,您正在 android 中创建自定义视图(为什么?)如果默认视图未提供我们代码中需要 use/implement 的某些功能,我们只需要自定义视图。
据我了解,您想使用自定义视图进行重用。这是一个很好的方法,但如果 android 提供了一些功能而不是你为什么要再次发明轮子,只需使用不同的布局,如果你想要一些额外的东西,只使用自定义视图。
好的,我想我明白了,不确定它是否是最好的解决方案,但它满足了我的要求。
所以它是这样的:
public class CustomView extends RelativeLayout
{
private Context context;
public TextView message;
public Button button;
public CustomView(Context context)
{
super(context);
// ---------------------------------------------------------
// store context as I like to create the views inside
// initViews() method rather than in the constructor
// ---------------------------------------------------------
this.context = context;
initViews();
initLayouts();
addViews();
}
public CustomView(Context context, AttributeSet attrs)
{
super(context, attrs);
// ---------------------------------------------------------
// store context as I like to create the views inside
// initViews() method rather than in the constructor
// ---------------------------------------------------------
this.context = context;
initViews();
initLayouts();
addViews();
}
public initViews()
{
// ----------------------------------------
// note "context" refers to this.context
// that we stored above.
// ----------------------------------------
message = new TextView(context);
...
button = new Button(context);
...
}
public initLayouts()
{
// --------------------------------------------------
// use Android layout params to position subviews
// within this custom view class
// --------------------------------------------------
message.setId(View.generateViewId());
button.setId(View.generateViewId());
RelativeLayout.LayoutParams messageLayoutParams = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT
);
message.setLayoutParams(messageLayoutParams);
RelativeLayout.LayoutParams buttonLayoutParams = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT
);
button.setLayoutParams(buttonLayoutParams);
}
public addViews()
{
// adding subviews to layout
addView(message);
addView(button);
}
}
现在我可以在我的任何 Activity:
中使用这个自定义视图
public class MainActivity extends ActionBarActivity {
// custom view instance
protected CustomView approvalView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
initViews();
}
public initViews()
{
...
approvalView = new CustomView(this);
approvalView.message.setText("1 + 1 = 2");
approvalView.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d("Logger", "Math formula approved! :D");
}
});
}
}
如果我们使用 XML 创建布局,则会使用 Inflater,这不是我喜欢做的事情,所以我以编程方式生成视图的布局 :D
上面"extends RelativeLayout"里面的"RelativeLayout"当然可以换成"LinearLayout"或者其他布局
为这个问题的一般访问者添加一个简单的答案...
您不能像使用 iOS UIView
. [一样将子视图添加到 Android View
如果您需要在 Android 中添加子视图,则使用 ViewGroup
子类之一(如 LinearLayout
、RelativeLayout
,甚至您自己的自定义子类) .
myViewGroup.addView(myView);
我正在尝试编程(不使用XML文件)在Android中创建自定义子视图(这就是我在[=85中的称呼) =]) 这基本上是一些基本视图(标签、按钮、文本字段等)组合成一个可重用的子视图 class,所以我可以在我的 UIViewControllers
或 Activity
中使用它在 Android.
我不知道 Android 中的正确术语是什么。似乎有一百万种不同的术语。
自定义视图、视图组、布局、小部件、组件,随便你怎么称呼它。
在 iOS 中,可以这样简单地完成:
CustomView.h
@interface CustomView : UIView
@property (nonatomic, strong) UILabel *message;
@property (nonatomic, strong) UIButton *button;
@end
CustomView.m
@implementation CustomView
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
[self initViews];
[self initConstraints];
}
return self;
}
-(void)initViews
{
self.message = [[UILabel alloc] init];
self.button = [[UIButton alloc] init];
[self addSubview:self.message];
[self addSubview:self.button];
}
-(void)initConstraints
{
id views = @{
@"message": self.message,
@"button": self.button
};
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[message]|" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[button]|" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[message][button]|" options:0 metrics:nil views:views]];
}
@end
现在我可以在我选择的任何 ViewController (Android Activity
) 中重复使用此自定义视图。
如何在 Android 中取得这样的成就?
我一直在环顾四周,从我在 Android 中收集到的内容中添加子视图,我将它们添加到 Layouts
:
RelativeLayout relativeLayout = new RelativeLayout(...);
TextView textView = new TextView(...);
relativeLayout.addSubview(textView);
这是否意味着我需要扩展 RelativeLayout
或 ViewGroup
?
查看此页面:http://developer.android.com/reference/android/view/ViewGroup.html
看来我们需要编写一些非常复杂的逻辑来布局自定义视图,例如:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int count = getChildCount();
// These keep track of the space we are using on the left and right for
// views positioned there; we need member variables so we can also use
// these for layout later.
mLeftWidth = 0;
mRightWidth = 0;
// Measurement will ultimately be computing these values.
int maxHeight = 0;
int maxWidth = 0;
int childState = 0;
// Iterate through all children, measuring them and computing our dimensions
// from their size.
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
// Measure the child.
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
// Update our size information based on the layout params. Children
// that asked to be positioned on the left or right go in those gutters.
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.position == LayoutParams.POSITION_LEFT) {
mLeftWidth += Math.max(maxWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
} else if (lp.position == LayoutParams.POSITION_RIGHT) {
mRightWidth += Math.max(maxWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
} else {
maxWidth = Math.max(maxWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
}
maxHeight = Math.max(maxHeight,
child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
childState = combineMeasuredStates(childState, child.getMeasuredState());
}
}
// Total width is the maximum width of all inner children plus the gutters.
maxWidth += mLeftWidth + mRightWidth;
// Check against our minimum height and width
maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
// Report our final dimensions.
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
resolveSizeAndState(maxHeight, heightMeasureSpec,
childState << MEASURED_HEIGHT_STATE_SHIFT));
}
我想做的就是在自定义视图中使用多个基本 android 标签、视图、按钮,如上面的 iOS 示例,为什么在 Android ?
我希望得到像这样简单的东西:
public class CustomView extends View
{
public RelativeLayout mainLayout;
public TextView message;
public Button button;
// default constructor
public CustomView()
{
...
initViews();
initLayouts();
addViews();
}
public initViews()
{
mainLayout = new RelativeLayout(this);
message = new TextView(this);
button = new Button(this);
...
}
public initLayouts()
{
// --------------------------------------------------
// use Android layout params to position subviews
// within this custom view class
// --------------------------------------------------
}
public addViews()
{
mainLayout.addView(message);
mainLayout.addView(button);
setContentView(mainLayout);
}
}
抱歉,我是真诚地尝试学习和构建一个基本的 Android 应用程序,而不是尝试 bash Android 的做事方式。
我知道如何在 Activity 中添加和布局子视图,过去两天我一直在这样做,但在自定义 View/View Group/Layout 中却不知道。我不想最终为 Android 应用程序中的每个 Activity 构建完全相同的子视图,这违背了良好的编码习惯,对吗? :D
这里只需要一些已经完成 iOS 和 Android 开发的其他人的指导。
编辑
我要找的好像是复合控件:http://developer.android.com/guide/topics/ui/custom-components.html
我会继续挖掘,希望能达到我想要的结果:D
只需要解决这个Inflater业务。
Android 和 ios 应用程序开发是两个不同的概念,每个都有自己的方式来执行您的任务。有时 android 有时 ios 很难开发一段代码。 要在 android 中创建视图 screen/design/GUI,您可以创建 XML 文件(推荐)或通过代码(这在某种程度上难以维护 w.r.t XML)。
对于您的问题,您不需要创建自己的 ViewGroup
或 RelativeLayout
或 LinearLayout
,例如如果您想使用 RelativeLayout
作为您视图的父级而不是使用 XML 您可以使用。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some Text"/>
</RelativeLayout>
如果您想实用地创建视图而不是使用
RelativeLayout parentRelativeLayout = new RelativeLayout(context);
RelativeLayout.LayoutParams parentParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
parentRelativeLayout.setLayoutParams(parentParams);
TextView childTextView = new TextView(context);
childTextView.setText("Some Text");
mRelativeLayout.addView(childTextView);
它只是一个示例代码,两者都具有相同的输出,但是使用编程方法,随着您的视图的增长,这将变得困难。
查看您的代码,您正在 android 中创建自定义视图(为什么?)如果默认视图未提供我们代码中需要 use/implement 的某些功能,我们只需要自定义视图。 据我了解,您想使用自定义视图进行重用。这是一个很好的方法,但如果 android 提供了一些功能而不是你为什么要再次发明轮子,只需使用不同的布局,如果你想要一些额外的东西,只使用自定义视图。
好的,我想我明白了,不确定它是否是最好的解决方案,但它满足了我的要求。
所以它是这样的:
public class CustomView extends RelativeLayout
{
private Context context;
public TextView message;
public Button button;
public CustomView(Context context)
{
super(context);
// ---------------------------------------------------------
// store context as I like to create the views inside
// initViews() method rather than in the constructor
// ---------------------------------------------------------
this.context = context;
initViews();
initLayouts();
addViews();
}
public CustomView(Context context, AttributeSet attrs)
{
super(context, attrs);
// ---------------------------------------------------------
// store context as I like to create the views inside
// initViews() method rather than in the constructor
// ---------------------------------------------------------
this.context = context;
initViews();
initLayouts();
addViews();
}
public initViews()
{
// ----------------------------------------
// note "context" refers to this.context
// that we stored above.
// ----------------------------------------
message = new TextView(context);
...
button = new Button(context);
...
}
public initLayouts()
{
// --------------------------------------------------
// use Android layout params to position subviews
// within this custom view class
// --------------------------------------------------
message.setId(View.generateViewId());
button.setId(View.generateViewId());
RelativeLayout.LayoutParams messageLayoutParams = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT
);
message.setLayoutParams(messageLayoutParams);
RelativeLayout.LayoutParams buttonLayoutParams = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT
);
button.setLayoutParams(buttonLayoutParams);
}
public addViews()
{
// adding subviews to layout
addView(message);
addView(button);
}
}
现在我可以在我的任何 Activity:
中使用这个自定义视图public class MainActivity extends ActionBarActivity {
// custom view instance
protected CustomView approvalView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
initViews();
}
public initViews()
{
...
approvalView = new CustomView(this);
approvalView.message.setText("1 + 1 = 2");
approvalView.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d("Logger", "Math formula approved! :D");
}
});
}
}
如果我们使用 XML 创建布局,则会使用 Inflater,这不是我喜欢做的事情,所以我以编程方式生成视图的布局 :D
上面"extends RelativeLayout"里面的"RelativeLayout"当然可以换成"LinearLayout"或者其他布局
为这个问题的一般访问者添加一个简单的答案...
您不能像使用 iOS UIView
. [一样将子视图添加到 Android View
如果您需要在 Android 中添加子视图,则使用 ViewGroup
子类之一(如 LinearLayout
、RelativeLayout
,甚至您自己的自定义子类) .
myViewGroup.addView(myView);