Intro:
I am attempting to add various Views to my custom RelativeLayout, i.e. Buttons, ImageViews, etc however none of them render/show.
Documentation:
As shown on numerous SO questions: here, here, here, here and many more,
I have the standard requirements for extending a layout, i.e. the 3 constructors, that being:
public RelativeLayout(Context context) {}
public RelativeLayout(Context context, AttributeSet attrs) {}
public RelativeLayout(Context context, AttributeSet attrs, int defStyleAttr){}
referred to here on Android Developer site.
Implementation:
My RelativeLayout named DiceRoller has the following implementation:
public class DiceRoller extends RelativeLayout {
private DieContainer dieContainer;
private Context mContext;
private int speed;
private Runnable moveDies;
private Handler handler;
private Timer timer;
public DiceRoller(Context context) {
super(context);
mContext = context;
init();
}
public DiceRoller(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}
public DiceRoller(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
init();
}
private void init() {
//source : https://stackoverflow.com/questions/28265286/custom-relative-layout-not-showing-child-views
setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
setGravity(Gravity.CENTER);
ImageView mainImage = new ImageView(mContext);
mainImage.setId(1994);
LayoutParams params = new LayoutParams(100, 100);
mainImage.setImageResource(R.drawable.die1);
mainImage.setLayoutParams(params);
addView(mainImage);
RelativeLayout.LayoutParams crossParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
crossParams.addRule(RelativeLayout.ALIGN_TOP | RelativeLayout.ALIGN_LEFT, mainImage.getId());
ImageView crossImage = new ImageView(mContext);
crossImage.setImageResource(R.drawable.die6);
crossImage.setLayoutParams(crossParams);
addView(crossImage);
TextView tv = new TextView(mContext);
tv.setText("hello world");
addView(tv);
}
}
Please Note: the contents of the init() method was purely to test if views were infact rendered. This was my last attempt at debugging the issue, previously I added views from my MainActivity aswell, obviously without success
With an associated layout file
<?xml version="1.0" encoding="utf-8"?>
<com.myapp.DiceRoller
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="1000px"
android:layout_height="1000px"
android:background="#color/colorAccent"
android:id="#+id/rollerBack">
</com.myapp.DiceRoller>
What is the problem:
The problem is simple. No child of the layout is rendered/shown/visible.
I attempted adding a child in my MainActivity, programmatically. It did not render. I attempted adding a child within this RelativeLayout class, it did not render.
Additional Info:
note: When adding views, I always added text or some image, I also set the X, Y values, also included RelativeLayout.LayoutParams() with the wrap option set.
When debugging this issue, if I added a view (ImageView, Button, etc), the layout has each child stored, and each child's parent is this RelativeLayout. Each child has a width, height, X, Y value and some content (either an image or text), thus the problem does not lie with the children.
I am at a loss, I have no idea why it doesn't render, any help would be greatly appreciated!
Related
I'm trying to make a LinearLayout align with the Software Keyboard when it is showing.
My LinearLayout contains an EditText to which the Software Keyboard is always being aligned.
The whole View (LinearLayout) looks like this:
When gaining focus to edit the EditText keyboard aligns itself to the EditText instead of the whole View:
I know that in the Material Design Library there is a TextInputLayout which also is a LinearLayout containing an EditText. When focusing on the EditText wrapped in the TextInputLayout the whole LinearLayout is aligned with the keyboard:
Now, I've seen people tell that I should add a windowSoftInputMode parameter in the <activity>:
android:windowSoftInputMode="adjustResize"
which does not work. Also I've seen many other answers on that issue but all of them referred to setting flags and parameters outside of the View itself but within the Activity's Window which is not what I want.
Here is the code that approximates mine - it has the dependencies that the CustomEditText has:
public class TestEditText extends LinearLayoutCompat {
public TestEditText(#NonNull Context context) {
super(context);
initTestEditText();
}
public TestEditText(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
initTestEditText();
}
public TestEditText(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initTestEditText();
}
// Layout in which there is an EditText - additional views, like buttons can be here
private LinearLayoutCompat textInputLayout;
private AppCompatEditText editText;
private void initTestEditText() {
setOrientation(VERTICAL);
setGravity(Gravity.CENTER_VERTICAL);
setBackgroundColor(Color.BLUE);
// Getting states from children - in this case from another LinearLayout
setAddStatesFromChildren(true);
prepareTextInputLayout();
prepareEditText();
}
private void prepareTextInputLayout() {
textInputLayout = new LinearLayoutCompat(getContext());
textInputLayout.setLayoutParams(
new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPx(128))
);
textInputLayout.setGravity(Gravity.CENTER_VERTICAL);
// Getting the states from children - in this case from an editText
textInputLayout.setAddStatesFromChildren(true);
addView(textInputLayout);
}
private void prepareEditText() {
editText = new AppCompatEditText(getContext());
LayoutParams params = new LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT,
1
);
editText.setLayoutParams(params);
editText.setGravity(Gravity.TOP);
editText.setBackgroundDrawable(null);
editText.setMaxLines(Integer.MAX_VALUE);
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
editText.setTextSize(14);
textInputLayout.addView(editText);
}
private int dpToPx(int dp) {
return (int) (dp * getResources().getDisplayMetrics().density);
}
}
There has to be some way to make the bottom of a View align with the Software Keyboard, because TextInputLayout does exactly that without setting any flags in the <activity>...
If You have any other idea, please help.
I'm trying to create a card game for Android, and I'm stuck on a confusing Issue.
I have a Custom View called CardBG that extends from the ViewFlipper class, so that i can flip the card around and show the front and the back. this works fine.
But i need to add some other things to the Cards, like a Textfield for example. So i created a Viewgroup in the belief that i can simply add Views to it. Adding this ViewGroup to my Activity results in nothing though.
What am I doing wrong? Is this a wrong approach alltogether?
I've also tried having Card extend a layout-class, such as RelativeLayout, but it gives me the same result.
Here is the relevant code, adding the cards has to be done dynamically, so no xml shenanigans:
TestActivity.java
public class TestActivity extends Activity {
RelativeLayout menuLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
menuLayout = (RelativeLayout) findViewById(R.id.layout_menu);
Card c = new Card(this, null);
c.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
menuLayout.addView(c);
}
}
Card.java
public class Card extends ViewGroup{
CardBG background;
TextView text1;
public Card(Context context, AttributeSet attrs) {
super(context, attrs);
Log.w("Card", "Constructor");
background = new CardBG(context, null);
background.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
this.addView(background);
}
(protected void onLayout is also in this file, but i do nothing in that method except calling super.onLayout)
}
CardBG.java
public class CardBG extends ViewFlipper{
ImageView blue;
ImageView red;
public CardBG(Context context, AttributeSet attrs) {
super(context, attrs);
Log.w("CardBG", "Constructor");
blue = new ImageView(context);
blue.setImageResource(R.drawable.card_blue);
blue.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
this.addView(blue);
red = new ImageView(context);
red.setImageResource(R.drawable.card_red);
red.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
this.addView(red);
//from here on out there are only onclick listener to test the flipping animations
}
While extending ViewGroup. You must have to implement onLayout method. In onLayout you need to call layout method on each child of this ViewGroup and provide desired position (relatively to parent) for them. You can check source code of FrameLayout (one of the simpliest subclasses of ViewGroup) to find out how it works.
Although, you may extend your view from RelativeLayout, LinearLayout or simple FrameLayout instead. RelativeLayout would give onLayout implementation by itself and provide relative positions to its children.
EDIT:
You might need to inflate layout in current view.
Sample Code:
public class Card extends RelativeLayout {
public Card(Context context, AttributeSet attr) {
super(context, attr);
View.inflate(context, R.layout.my_card_layout, this);
}
}
I got a custom view extending RelativeLayout.
After inflating it with an xml layout I want to add another view to it.
I want to add the view above the existing one.
That seems to work but the RelativeLayout does not resize itself.
It looks like the older contents get overwritten, or maybe scroll down, where they
are not visible.
I create my custom RelativeLayout with:
public class BottomBarEdit extends RelativeLayout {
private Context context;
public BottomBarEdit(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
View.inflate(context, R.layout.lay_bottom_bar_edit, this);
I try to add a view dynamically with:
// create layout parameters
RelativeLayout.LayoutParams lparams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
lparams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
lparams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
lparams.addRule(RelativeLayout.ABOVE, R.id.bottom_bar_buttons);
// RelativeLayout editMain = (RelativeLayout)
// findViewById(R.id.bottom_bar_edit);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View noteBar = inflater.inflate(R.layout.lay_bottom_bar_notes, null);
this.addView(noteBar, lparams);
Any idea whats going wrong?
Thanks!
I'm trying to create a view that has an ImageView with a TextView on top of it.
I'm stuck trying to find any good examples on this so I'm hoping someone can tell me what I've done wrong or where to look for examples. I've seen http://developer.android.com/guide/topics/ui/custom-components.html#compound but only really describes the minimal requirements.
I've found a couple things like Creating Compound Controls With Custom XML Attributes but my setup is a tad different.
My code is below, which extends LinearLayout and am not sure if that is even the way to go. Nothing displays in the layout.
ImageWithOverlay
public class ImageWithOverlay extends LinearLayout {
ImageView image;
TextView text;
public ImageWithOverlay(Context context) {
super(context);
setupDisplay(context);
}
public ImageWithOverlay(Context context, AttributeSet attrs) {
super(context, attrs);
setupDisplay(context);
}
public ImageWithOverlay(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setupDisplay(context);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
image.draw(canvas);
text.draw(canvas);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void setupDisplay(Context context) {
image = new ImageView(context);
image.setImageResource(R.drawable.flowers);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
image.setLayoutParams(lp);
text = new TextView(context);
text.setText("testing");
lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
text.setLayoutParams(lp);
}
}
status.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.package.blah.ImageWithOverlay
android:id="#+id/imageWithOverlay1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
</com.package.blah.ImageWithOverlay>
</RelativeLayout>
Use a RelativeLayout instead of a LinearLayout, this will allow you to place the text over the image.
The reason why they aren't appearing is that they haven't been added using addView, so call this after you've set each one's LayoutParams.
Remove the onDraw() call, this isn't used for ViewGroups unless you explicitly request it do be. And once the Views are added they'll be drawn automatically.
I have created a custom view named MyDraw ,this is my MyDraw code,
public class MyDraw extends View {
public MyDraw(Context context) {
super(context);
}
public MyDraw(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyDraw(Context context, AttributeSet attrs) {
super(context, attrs);
}
........................................
}
I have added the view in XML file using package name. It is working fine. Now I want to set height and width for the MyDraw in run time,for that i have used following code,
mMyDraw.setLayoutParams(new LayoutParams(220, 300));
but i got Exception like,
java.lang.ClassCastException: android.view.ViewGroup$LayoutParams
How to solve this exception?
please help me..
You must override the onMeasure() method of the View.
For a nice example you can check here: http://kahdev.wordpress.com/2008/09/13/making-a-custom-android-button-using-a-custom-view/
And a very cool video that I would recommend is here: http://marakana.com/forums/android/general/563.html
Hope this helps!
Override the onMeasure() method, have a look here
There is a simple way:
based on our custom view parent class we can use layout param.
for example if our custom view is extended from FrameLayout:
FrameLayout.LayoutParams params = (LayoutParams) findViewById(R.id.root).getLayoutParams();
params.width = newwidth;
params.height = newHeight;
setLayoutParams(params);
where "R.id.root" is id of our root view in custom_view.xml that in this case is FrameLayout.