Create an Android subview, e.g. iOS subviews

I am trying to programmatically (without using XML files) to create custom subtitles in Android (this is what I call it in iOS), which basically is a series of basic views (shortcuts, buttons, text fields, etc.) combined into a reusable subview class, so I can use it inside my UIViewControllers or Activity in Android.

I do not know what the correct terminology is in Android. There seem to be a million different terms.

Custom View, ViewGroups, Layouts, Widgets, Components, everything you want to name.

On iOS, this is done as follows:

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 

Now I can reuse this custom view in any ViewController (Android Activity ) that I have selected.

How can one achieve something like this in Android?

I look around and from what I'm going to in Android to add subviews, I add them to Layouts :

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

Does this mean that I need to extend RelativeLayout or ViewGroup ?

Looking at this page: http://developer.android.com/reference/android/view/ViewGroup.html

It seems that we need to write some really complex logic for the layout of the user view, for example:

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

All I'm trying to do is use a few basic android shortcuts, views, buttons in a custom view, such as the iOS example above, why is it so complicated in Android?

I was hoping for something simple:

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

I'm sorry that I am sincerely trying to learn and create a basic Android application, rather than trying to bash Android to do something.

I know how to add and compose objects within an Activity and have been doing this for the last two days, but not inside the user group View / View Group / Layout. I don’t want to design the same subview for each of my actions in an Android application that just contradicts good coding practice ?: D

You just need to learn a little from others who have done both iOS and Android development.

Edit

It seems that what I'm looking for is called Compound Control: http://developer.android.com/guide/topics/ui/custom-components.html

I will continue to dig and hope to get the result that I will: D

You just need to develop this Inflater business.

+6
source share
3 answers

Ok, I think I understood, not sure if this is the best solution, but it does what I want.

So it looks something like this:

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

Now I can use this custom view in any of my actions:

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

Inflater is used if we create our layout using XML, which is not something I like to do, so I generated my view layout programmatically: D

The above “RelativeLayout” in “extends RelativeLayout” can be replaced with “LinearLayout” or other layouts, of course.

+1
source

Android and ios application development are two different concepts, each of which has its own way to accomplish your task. Sometimes it’s hard to develop a piece of code in android, and sometimes in ios. To create a view / design / GUI screen in android, you can create an XML file (recommended) or by code (which is somehow difficult to support wrt XML).

For your question you do not need to create your own ViewGroup or RelativeLayout or LinearLayout for example. if you want to use RelativeLayout as a parent for your view than using XML you can use.

 <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> 

If you want to create your presentation pragmatically than use

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

Its just a sample code has the same result, but with a programmatic approach it will be tricky as your look grows.

In your code, which you create a custom view (why?) In android, we only need custom views, if the default views do not provide some functionality that we must use / implement in our code. As I understand it, you want to use custom views for reuse. Its a good approach, but if the android provides some functionality than why you are trying to invent a wheel, just use different layouts, use only custom views if you want something extra.

+1
source

To add a simple answer for the general visitor to this question ...

You cannot add subviews to Android View as you can with iOS UIView .

If you need to add subviews to Android, use one of the ViewGroup subclasses (e.g. LinearLayout , RelativeLayout or even your own custom subclass).

 myViewGroup.addView(myView); 
0
source

Source: https://habr.com/ru/post/986916/


All Articles