创建类似iOS子视图的Android子视图
我试图以编程方式创建Android中的自定义子视图(我在iOS中称之为自定义子视图),这基本上是一系列基本视图(标签、按钮、文本字段等)放在一个可重用的子视图类中,这样我就可以在Android中的创建类似iOS子视图的Android子视图,android,ios,android-custom-view,android-viewgroup,Android,Ios,Android Custom View,Android Viewgroup,我试图以编程方式创建Android中的自定义子视图(我在iOS中称之为自定义子视图),这基本上是一系列基本视图(标签、按钮、文本字段等)放在一个可重用的子视图类中,这样我就可以在Android中的UIViewControllers或Activity中使用它 我不知道Android的正确术语是什么。似乎有一百万种不同的术语 自定义视图、视图组、布局、小部件、组件,无论您如何称呼它 在iOS中,这样做很简单: public class CustomView extends View { pu
UIViewControllers
或Activity
中使用它
我不知道Android的正确术语是什么。似乎有一百万种不同的术语
自定义视图、视图组、布局、小部件、组件,无论您如何称呼它
在iOS中,这样做很简单:
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);
}
}
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);
}
}
CustomView.h
CustomView.m
现在我可以在我选择的任何ViewController(AndroidActivity
)中重用此自定义视图
在安卓系统中,人们是如何做到这一点的
我一直在环顾四周,从我在Android中收集的信息中,为了添加子视图,我将它们添加到布局中
:
RelativeLayout relativeLayout = new RelativeLayout(...);
TextView textView = new TextView(...);
relativeLayout.addSubview(textView);
这是否意味着我需要扩展RelativeLayout
或ViewGroup
请看本页:
似乎我们需要编写一些非常复杂的逻辑来布局自定义视图,例如:
@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应用程序,而不是试图抨击Android的做事方式
我知道如何在活动中添加和布局子视图,在过去的两天里我一直在这样做,但在自定义视图/视图组/布局中却没有。我不想在Android应用程序中为我的每个活动构建完全相同的子视图,这与良好的编码实践背道而驰,对吧D
在这里,我们只需要从其他同时开发过iOS和Android的人那里得到一些指导
编辑
看起来我要找的是一个复合控件:
我会继续努力,希望能达到我想要的结果:D
只需要解决这个充气机业务。Android和ios应用程序开发是两个不同的概念,每个都有自己的方式来执行任务。有时在android中开发一段代码很困难,有时在ios中也很困难。 要在android中创建视图屏幕/设计/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>
这只是一个示例代码,两个代码都有相同的输出,但随着视图的增长,使用编程方法将很困难
查看您的代码您正在创建自定义视图(为什么?)在android中,如果默认视图没有提供一些我们需要在代码中使用/实现的功能,我们只需要自定义视图。
据我所知,您希望使用自定义视图进行重用。这是一个很好的方法,但如果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);
}
}
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创建布局,就会使用充气器,我不喜欢这样做,所以我以编程方式生成了视图的布局:D
“扩展相对布局”中的上述“相对布局”当然可以替换为“线性布局”或其他布局。要为普通访问者添加此问题的简单答案 您不能像使用iOS
UIView
那样,向Android视图添加子视图
如果您需要在Android中添加子视图,那么可以使用ViewGroup
子类之一(比如LinearLayout
,RelativeLayout
,甚至您自己的自定义子类)
为什么不呢?在开发应用程序时,有时需要在界面中使用可重用组件,例如自定义弹出警报确认对话框,其中可能包括标题标签、问题标签、文本字段和确认按钮。你不想重复你的代码,在每一个单独的活动中构造相同的弹出视图。您可以编写一个可重用的自定义视图,将其导入活动并创建其实例。这不是重新发明轮子,而是使用基本组件构建更复杂的可重用视图。我理解你的观点,我推荐你这样做。我的意思是,如果并且仅当您需要默认情况下不可用的更多/额外内容时,您应该使用自定义视图。是的,如果你想在整个应用程序中使用相同的弹出窗口,那么你可以在代码中创建弹出窗口警报,并在任何时间、任何地点调用函数/方法。Android提供了一个弹出对话框,如果你要去创建自定义对话框扩展对话框,它与默认对话框相同,而不是再次发明轮子,但是如果你要使用默认对话框,使用它的属性进行化妆和使用,这是可重用的。我不认为你会这样做。我想我在Android中称之为复合控件:。基本的Android对话框视图(带有取消和确认按钮的标签)是谷歌为我们编写的复合视图。它将文本视图和按钮视图合并成一个新的可重用类,称为“Dialog”。这个概念类似于扩展基类的面向对象编程。子类继承自基类,并添加了自己的属性和函数,它不是在重新发明轮子。例如,如果我得到一个“Square”类,它就有一个宽度和高度。如果我从该类继承并添加一个新属性“length”来形成一个名为“Cube”的新类,这是不是在重新发明轮子?同样,我从Android View类继承并添加新的“属性”,例如TextView、Yes按钮和No按钮,并将该类称为“TrueOrFalseView”。这不是重新发明轮子,而是扩展视图类
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");
}
});
}
}
myViewGroup.addView(myView);