Reputation: 1161
So I am just playing around in android and found something really strange. Before I states what is wrong let me give the code.
Here is my Custom Viewgroup code:
package com.ayto.android.cleverpad;
import android.content.Context;
import android.graphics.Color;
import android.graphics.RectF;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
public class noteLayout extends ViewGroup {
float leftOrientationSize = 0;
float rightOrientationSize=0;
public noteLayout(Context activityContext)
{
super(activityContext);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
RelativeLayout mainParent = (RelativeLayout) getParent();
for (int i = 0; i < getChildCount(); i++) {
final View child = getChildAt(i);
child.measure(MeasureSpec.makeMeasureSpec((mainParent.getWidth()/2)-30,MeasureSpec.EXACTLY),MeasureSpec.makeMeasureSpec(200,MeasureSpec.AT_MOST));
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int numberOfChild = getChildCount();
for (int i = 0;i<numberOfChild;i++){
View childView = getChildAt(i);
float childHeight = (float) childView.getMeasuredHeight();
float childWidth = (float) childView.getMeasuredWidth();
RectF rect = new RectF();
rect.bottom = childHeight+20;
rect.top = 20;
rect.left = 20;
rect.right = childWidth+20;
childView.layout((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom);
}
}
}
and here is the xml file that I add (addView()
) to CustomView:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" android:background="@android:color/holo_blue_bright">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Title"
android:id="@+id/displayNoteTitle"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Test"
android:id="@+id/displayNote"
android:padding="5dp"
android:paddingBottom="10dp"
android:paddingLeft="5dp"
android:ellipsize="end"
android:layout_above="@+id/displayNoteTitle"
android:layout_alignRight="@+id/displayNoteTitle"
android:layout_alignEnd="@+id/displayNoteTitle" />
</RelativeLayout>
So basically what I did was create an instance of my noteLayout note = new noteLayout(getApplicationContext())
and use the layout inflater to inflate the views from my xml. Then I use noteLayout.addView()
to add the inflated view into my custom viewgroup. My problem is that only the textview with the android:Text = "Title"
is displayed and the other seem to not render. I am not so sure why this is the case.
ActivityMain
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.RelativeLayout;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
noteLayout test = new noteLayout(getApplicationContext());
test.addView(getLayoutInflater().inflate(R.layout.Layout,null));
((RelativeLayout) findViewById(R.id.mainActivity)).addView(test);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Upvotes: 1
Views: 272
Reputation: 37798
Okay. So after our discussion, managed to see what was happening.. I'll explain it thoroughly as it might be confusing.. First of.. In the MainActivity the noteLayout
was initialized like so:
noteLayout test = new noteLayout(getApplicationContext());
and is then passed with another RelativeLayout
that contains the 2 TextView
s :
((RelativeLayout) findViewById(R.id.mainActivity)).addView(test);
So now, the hierarchy would look like this:
RelativeLayout(activity_main)
-- RelativeLayout(one from xml)
---- TextView(title)
---- TextView(body)
And in the code of noteLayout
in onMeasured()
this line appears:
RelativeLayout mainParent = (RelativeLayout) getParent();
-- which means that the mainParent it gets is the RelativeLayout of the MainActivity (R.layout.activity_main
), after that, the loop was made:
for (int i = 0; i < getChildCount(); i++) {
final View child = getChildAt(i);
child.measure(MeasureSpec.makeMeasureSpec((mainParent.getWidth()/2)-30,MeasureSpec.EXACTLY),MeasureSpec.makeMeasureSpec(200,MeasureSpec.AT_MOST));
}
To verify this, I put a log inside the loop and it returns only 1 child. So what I did is modify the loop like so:
RelativeLayout mainParent = (RelativeLayout) getParent();
final RelativeLayout child = (RelativeLayout) getChildAt(0);
child.measure(MeasureSpec.makeMeasureSpec((mainParent.getWidth() / 2) - 30, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((mainParent.getHeight() / 2) - 30, MeasureSpec.EXACTLY));
Log.d("SAMPLE", "RelativeLayout Child childcount: " + child.getChildCount());
for (int i = 0; i < child.getChildCount(); i++) {
Log.d("SAMPLE", "In loop: " + i);
final View childOfChild = child.getChildAt(i);
childOfChild.measure(MeasureSpec.makeMeasureSpec((mainParent.getWidth() / 2) - 30, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(200, MeasureSpec.AT_MOST));
}
You can see here that I treated the child of the first RelativeLayout
as another RelativeLayout
then made the loop using the child.getChildCount()
. Also (I just added default measure for the second RelativeLayout, you can edit it to whichever you prefer). This calls the TextView
s properly now as to what you would expect from your code.
Here is a screenshot after running the code.
So overall. I just edited out the onMeasure()
part of your code.. The main problem was just with which layout you were referring and looping. :D
Upvotes: 1