0

Basically as the title says. I have a class that extends LinearLayout and I want that LinearLayout to have a child TextView inside. The problem is, the TextView does not seem to appear.

Here is what I have so far, what exactly am I doing wrong?

Update: I Changed my code as following as you guys have suggested, and my TextView still does not appear....

public class CalendarCourseView extends LinearLayout {

    private int height;
    private int topMargin;
    private Course course;

    public CalendarCourseView(Context context, Course course, int topMargin,
                              int height) {
        super(context);
        final DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
        this.topMargin = (int) TypedValue
                .applyDimension(TypedValue.COMPLEX_UNIT_DIP, topMargin, displayMetrics);
        this.height = (int) TypedValue
                .applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, displayMetrics);
        this.course = course;
        this.setBackgroundColor(course.getColor());
        setTextView();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), this.height);
        ((MarginLayoutParams) getLayoutParams()).topMargin = topMargin;
    }

    private void setTextView() {
        TextView textView = new TextView(this.getContext());
        LayoutParams params = new LayoutParams(new LinearLayout.LayoutParams(ViewGroup
                .LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        textView.setLayoutParams(params);
        textView.setText(course.getName());
        this.addView(textView);
    }

}

Update: I pinned-point the problem. It is with onMeasure. I believe the TextView is not placed in the same position as the LinearLayout after height and topMargin change.

Update: Fixed it simply by changing calling super.onMeasure on onMeasure.

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, this.height);
        ((MarginLayoutParams) getLayoutParams()).topMargin = topMargin;
    }

I believe it is because setMeasuredDimension(int, int) only changes the dimension of the View and not the children. I would also have had to override onLayout. Calling the super.onMeasure also changes the children and simplified things.

6
  • I believe this is already answered by @Luksprog here: stackoverflow.com/questions/13394181/… Commented Apr 30, 2017 at 21:55
  • 1
    onMeasure usually gets called more than once. Adding stuff there to the layout is usually a bad idea. And you should use MeasureSpec.getSize(widthMeasureSpec) and not just pass in widthMeasureSpec, because it is not a size by itself. Commented Apr 30, 2017 at 22:03
  • @FlorentSpahiu I'm still unsure how does that affect the TextView not appearing? The LinearLayout is inflated just fine... Commented Apr 30, 2017 at 22:06
  • @DavidMedenjak where do you suggest I add the TextView then? Commented Apr 30, 2017 at 22:07
  • 3
    Either in the constructor or in onFinishInflate (which only works if inflating it from xml), or add some check to prevent it from being added again Commented Apr 30, 2017 at 22:11

2 Answers 2

2

Check your code to see if

course.getName()

has a value. Just for testing purposes, you can say

textView.setText("MyCourseName");

for example.

This example below is working correctly for me.

public class CustomView extends LinearLayout {

    public CustomView(Context context) {
        super(context);
        Log.d("CusotmView", "on constructor after super(context)");

        TextView textView = new TextView(this.getContext());
        LayoutParams params = new LayoutParams(new LinearLayout.LayoutParams(ViewGroup
                .LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        textView.setLayoutParams(params);
        textView.setText("MyText");
        this.addView(textView);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.d("CustomView", "onMeasure");
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the input. This does indeed work, and helped me find that the bug was with the positioning of the TextView.
If it solved your problem, mark is as correct answer. Cheers
0

As it's been mentioned, calling setTextView from the onMeasure method is a bad idea. onMeasure is not always called consistentyly, like onCreate or onStart. On top of that, I don't think that you are properly adding the textView to the main view. I would put the setTextView inside the constructor like so:

public MyView(Context context, Course course, int topMargin,
                              int height) {
        super(context);
        final DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
        this.topMargin = (int) TypedValue
                .applyDimension(TypedValue.COMPLEX_UNIT_DIP, topMargin, displayMetrics);
        this.height = (int) TypedValue
                .applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, displayMetrics);
        this.course = course;
        super.setBackgroundColor(course.getColor());
        this.setTextView();
    }

I will also add that you aren't adding the TextView to the correct view. You are adding it to the super class, rather than the view that has been created. You are going to need to get a reference to the view you are trying to add the layout to. Maybe it would look something like this:

private void setTextView() {
        TextView textView = new ResponsiveTextView(super.getContext());
        LayoutParams params = new LayoutParams(new LinearLayout.LayoutParams(ViewGroup
                .LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        textView.setLayoutParams(params);
        textView.setText(course.getName());
        //You should reference the object being created rather than the super class
        this.addView(textView);

    }

6 Comments

If you post the XML, like I asked earlier, it would be more helpful. :)
There is no associated xml, I'm using it as a custom LinearLayout. @BlackHatSamurai
Yep, I tried hard-coded string on setText as well and didn't work.
Can you post the class where you create the MyView object?
I simply call the constructor and add it to a view. Please see updated post
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.