1

Within a RecyclerView, I'm creating new CustomViews and then setting their Layout Parameters, like so:

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    CustomView customView= new CustomView(parent.getContext() /*, ...otherCustomArgs*/);
    customView.setLayoutParams(new ViewGroup.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    ));
    // ...
}

Now I've observed that there are quite a few constructors for LinearLayout - the class from which my CustomView extends.

/**
    {@link LinearLayout(Context)}
    {@link LinearLayout(Context, AttributeSet)}
    {@link LinearLayout(Context, AttributeSet, int)}
    {@link LinearLayout(Context, AttributeSet, int, int)}
*/

Now obviously there's a standard way to pass the width / height at instantiation - through to one of these constructors, which is how layout_width/height from XML layouts is passed into the class.

To keep things standard, I want to use one of these within my custom constructor, i.e:

CustomView extends LinearLayout {
    CustomView(Context context, LayoutArgs layoutArgs, Object... otherCustomArgs){
        this(context, ...layoutArgs);
        // Use otherCustomArgs
    }
}

I guess, because this custom constructor will never actually be used within XML layouts, it's not necessary to conform to standard construction, but there may be other things the default constructors are doing with XML layout_width/height that setLayoutParams wouldn't.

Tobiq
  • 2,489
  • 19
  • 38
  • 1
    "Now obviously there's a standard way to pass the width / height at instantiation - through to one of these constructors" – Nope. `LayoutParams` aren't handled in a `View`'s constructor. Generally – e.g., when inflated from layout XML – they are created by passing a `View`'s `AttributeSet` to the parent `ViewGroup`'s `generateLayoutParams(AttributeSet)` method, and then set on the `View` with `setLayoutParams()`. This happens after instantiation, kinda like what you're already doing. – Mike M. Apr 07 '19 at 02:19
  • That answers the questions I posed for @ianhanniballake – Tobiq Apr 07 '19 at 02:21
  • I guess then I'd actually be skipping a lot of unnecessary work by not doing it the way I am currently. i will however move the call to `setLayoutParams` to inside the custom constructor. – Tobiq Apr 07 '19 at 02:22
  • 1
    Yeah, if I'm understanding what you're saying, it is. I can't really think of any other way, really. `setLayoutParams()` is exactly what `LayoutInflater` itself does, for example. – Mike M. Apr 07 '19 at 02:23

1 Answers1

1

As per the Layouts, Attributes, and You blog post:

To change things on a child-by-child basis, layouts use a different mechanism in the form of layout_ attributes, which are added to child Views. These attributes are different because layout_ attributes are instructions for the parent ViewGroup, not for the View itself.

Therefore your CustomView won't get layout params passed to you - they're passed to whatever layout you add your CustomView to. The parent layout will then use these values to measure and layout your CustomView.

ianhanniballake
  • 191,609
  • 30
  • 470
  • 443