创建像 iOS 子视图一样的 Android 子视图



我正在尝试以编程方式(不使用XML文件)在Android中创建自定义子视图(这就是我在iOS中所说的),这基本上是许多基本视图(标签,按钮,文本字段等)组合成一个可重用的子视图类,以便我可以在Android中的UIViewControllersActivity中使用它。

我不知道安卓的正确术语是什么。似乎有一百万个不同的术语。

自定义视图,视图组,布局,小部件,组件,无论您想怎么称呼它。

在iOS中,这是简单地完成的:

自定义视图.h

@interface CustomView : UIView
@property (nonatomic, strong) UILabel *message;
@property (nonatomic, strong) UIButton *button;
@end

自定义视图.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

现在,我可以在我选择的任何视图控制器(AndroidActivity)中重用此自定义视图。

如何在Android中实现类似的东西?

我一直在环顾四周,从我在 Android 中收集的内容来看,要添加子视图,我将它们添加到Layouts

RelativeLayout relativeLayout = new RelativeLayout(...);
TextView textView = new TextView(...);
relativeLayout.addSubview(textView);

这是否意味着我需要延长RelativeLayoutViewGroup

查看此页面: 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应用程序,而不是试图抨击Android的做事方式。

我知道如何在活动中添加和布局子视图,并且过去两天一直在这样做,但不是在自定义视图/视图组/布局中。我不想最终为我在 Android 应用程序中的每个活动构建完全相同的子视图,这违反了良好的编码实践,对吗?:D

只需要从其他同时完成iOS和Android开发的人的指导

编辑

似乎我正在寻找的被称为复合控件:http://developer.android.com/guide/topics/ui/custom-components.html

我会继续挖掘,希望能达到我想要的结果:D

只需要解决这个 Inflower 业务。

好的,我想我明白了,不确定它是否是最好的解决方案,但它可以满足我的需求。

所以它是这样的:

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); 
}
}

现在,我可以在我的任何活动中使用此自定义视图:

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 创建布局,则使用 Infheater,这不是我喜欢做的事情,所以我以编程方式生成视图的布局:D

当然,"扩展相对布局">

中的上述"相对布局"可以替换为"线性布局"或其他布局。

为这个问题的普通访问者添加一个简单的答案......

您无法像使用 iOSUIView那样向 AndroidView添加子视图。

如果您需要在 Android 中添加子视图,请使用ViewGroup子类之一(如LinearLayoutRelativeLayout,甚至是您自己的自定义子类)。

myViewGroup.addView(myView);

Android和iOS应用程序开发是两个不同的概念,每个都有自己的方法来执行任务。有时很难在Android中开发一段代码,有时在ios中开发。 要在android中创建视图屏幕/设计/GUI,您可以创建XML文件(推荐)或通过代码(这在某种程度上难以维护w.r.t XML)。

对于您的问题,您不需要创建自己的ViewGroupRelativeLayoutLinearLayout例如,如果您想使用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中,如果默认视图没有提供一些我们需要在代码中使用/实现的功能,我们只需要自定义视图。 据我了解,您希望使用自定义视图进行重用。这是一个很好的方法,但如果 android 提供了一些功能,而不是你为什么要再次发明轮子,只需使用不同的布局,如果你想要额外的东西,只使用自定义视图。

相关内容

最新更新