I am trying to make an app that lets the user store and saves contacts. It can save, but it has problems listing.
I have a for loop that runs through the database and prints a set of data for each contact (each row), an image (actually its a string because it passes the path) and a string. It prints them in a scrollview with a linear layout for each contact (each contact has a linear layout of its own, so that i can let one contact occupy a row each). The images come out, however, the textviews are nowhere to be found.
Using log.d(textview.getText()); it confirms that the textviews are created and take up space.
http://chesnutcase.heliohost.org/derpbox/itv1.png
Two "contacts" with names, not printed out. The space inbetween is presumbly by the textview.
http://chesnutcase.heliohost.org/derpbox/itv2.png
Another two "contacts", but without names. The dont have a space between each other. Or at least, a significantly smaller space.
Code:
DatabaseHandler db = new DatabaseHandler(this);
int a = (int) (long) db.countRows();
LinearLayout theLayout = (LinearLayout)findViewById(R.id.contactsList);
for(int i = 0;i<a;i++){
ImageButton image = new ImageButton(this);
int density=getResources().getDisplayMetrics().densityDpi;
LinearLayout.LayoutParams vp = new LinearLayout.LayoutParams(density,density, 0.5f);
image.setLayoutParams(vp);
image.setScaleType(ImageView.ScaleType.FIT_END);
int b = a - i;
try {
image.setImageBitmap(decodeUri(Uri.parse(db.getContactData("photo_path")[i])));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
theLayout.addView(image);
TextView tv = new TextView(this);
tv.setText(db.getContactData("name")[i]);
Log.d("UserLog","name is " + db.getContactData("name")[i]);
Log.d("UserLog","textfield contains " + tv.getText());
LinearLayout.LayoutParams vp2 = new LinearLayout.LayoutParams(0,0,1f);
tv.setLayoutParams(vp2);
tv.setBackgroundColor(Color.RED);
theLayout.addView(tv);
}
Any solutions? Thanks in advance
Double check which orientation you've applied to the LinearLayout of your contacts list.
You are setting bad LayoutParams to your TextView. You're making your TextView 0px by 0px with a weight of 1.
LinearLayout.LayoutParams vp2 = new LinearLayout.LayoutParams(0,0,1f);
tv.setLayoutParams(vp2);
Try using one of the MATCH_PARENT or WRAP_CONTENT constants. They're listed here: http://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html#MATCH_PARENT
If you want your TextView to take up the remaining width of the screen I would leave the weight as 1, the width as 0, but you need to set the height to a constant like WRAP_CONTENT.
You're also setting the size of your ImageView to the device screen density (which is a constant) instead of setting a scaling size based off your screen density.
You probably need to call requestLayout(); in order to update the current view layout.
theLayout.requestLayout();
Also it seems you are creating a view with 0 width and 0 height with that layout params:
LinearLayout.LayoutParams vp2 = new LinearLayout.LayoutParams(0,0,1f);
It is better to use ListView for such list.
You will need to write only one Adapter, that's represent logic for creating one row on list.
I would recommend using a CursorAdapter and a layout xml file, this way you can design it to look exactly how you want, and preview it. It is a lot easier than setting all those fiddly LayoutParams
If you have to create them dynamically you may find the text colour is the same as the background, try setting it to something visible like bright red for testing. If you still don't see the text it may be that it's visibility isn't set to View.VISIBLE finally the layout may not be the correct size, a handy tip for this is set the background to a suitably eye catching colour, even if there is no text you should see a shaded block.
Related
I want to create a Card Deck app that contains (lets say) from 0 to 10 total cards as it runs.
I have a RelativeLayout created with XML inside a parent layout, this RelativeLayout has width to match parent and height to wrap content.
Now i want to add fixed size buttons (cards) to that layout and when the don't have room they must not deformate but be scaled and placed on top of the other.
When i just add them it happens this:https://postimg.org/image/ic8pmaju7/
But i want to achieve something like this :https://postimg.org/image/567dj49j9/
*For second image i used setmargins(xleft,x,x,x);...xleft++; , but when i have 2 or 5 buttons they keep being on the top of the other button, instead of just use the free space.
So im asking if there is a layout or a method that when there is no room (small screen or too many buttons) puts buttons on top and next of the other button than deforming them.
ConstraintLayout allows you to create large and complex layouts with a flat view hierarchy (no nested view groups). It's similar to RelativeLayout in that all views are laid out according to relationships between sibling views and the parent layout, but it's more flexible than RelativeLayout and easier to use with Android Studio's Layout Editor.
Using the ConstraintLayout you can do it, and spending less user processing than if you use nested LinearLayouts.
To put button next to button and adjust them in according to screen size, you can use the Chains, that is a resource of ConstraintLayout.
Chains provide group-like behavior in a single axis (horizontally or vertically). The other axis can be constrained independently.
Click here to read more about ConstraintLayout and Click here to read more about Chains.
Ok, guys i tryied what you suggested but i couldnt't achieve what i wanted, so i spent HOURS working on it and i ended up with some math and some help of fuctions to (at last) find the solution. I will post my code if someone wants to give a try:
public void ChangeView(View view) {
//here we put number of cards that we want to be scaled and displayed (cards=buttons)
int CardMax=13;//13 for example!!!
//getting scale for dpi of phone screen(i think??)
final float scale = getResources().getDisplayMetrics().density;
// getting some values we need to know
// **THESE VALUES DEPEND FROM SCREEN RESOLUTION OR THE SIZE OF BUTTON**
int layWidth = layout.getWidth(); //getting layout width that equals screen width(in pixels)
int btnWidth = (int) (50 * scale); //setting and scaling the width of the button for any screen
int maxLayfit=layWidth/btnWidth; //getting how many buttons can be added to layout without deformation
int layMidWidth = layWidth / 2; //getting layouts half width (that helps to start adding buttons from middle)
int StrMeasur; // this help how to start setting the buttons
if (CardMax <= maxLayfit) { // if cards are less than Layout can hold without deformation
StrMeasur = CardMax; // StrMeasur equals number of cards
} else {
StrMeasur = maxLayfit; // else equals max number of cards without deformation
}
int pointer=0; //pointer that will say where to put the first button
pointer = layMidWidth - ((btnWidth / 2) * StrMeasur);//depends of how many cards we have and button width
int start =layMidWidth-((btnWidth / 2) * StrMeasur);
int nextBtn = 0; //nextBtn says where to put the next button
//here we set the buttons on top and next to the previous button as we need **TRICKY PART**
if (CardMax > maxLayfit-1) { //if number of cards is bigger than the number the layout can hold
//then we calculate first card position (start/pointer) and the last card position(=layout width-button width)
//we find how many equal parts the layout has to be divided with the given cards
//and we get the width of the part to set it as pointer of the next card place
nextBtn =(((layWidth-start)-btnWidth)-start)/CardMax;
}else{
nextBtn=btnWidth; //else the pointer just set buttons next to the other
}
//Here we display all the buttons
for (int i = 0; i < CardMax; i++) {
Button cards = new Button(this);
cards.setWidth(btnWidth);
cards.setHeight((int) (90 * scale));
RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params2.setMargins(pointer, 0, 0, 0);
cards.setLayoutParams(params2);
cards.setText("" + (i + 1));
cards.setId(i);
layout.addView(cards);
pointer = pointer + nextBtn;
}
}
I belive it will work on any screen.
I'm creating a number of edit texts next to each other programmatically using RelativeLayout. The default width of each edit text is wrap_content, but when the edit text reaches the edge of the screen, it visually changes it's sizes. So how can I make it move to the next line when this happens?
private EditText createEditText(EditText editText1, EditText editText2, String word){
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
editText.getLayoutParams().width,
editText.getLayoutParams().height
);
layoutParams.addRule(RelativeLayout.RIGHT_OF, editText1.getId());
layoutParams.addRule(RelativeLayout.BELOW, textView.getId());
layoutParams.leftMargin += 60;
editText2.setHint("" + word);
editText2.setHintTextColor(editText.getSolidColor());
editText2.setBackgroundResource(R.drawable.rounded_edittext);
editText2.setLayoutParams(layoutParams);
editText2.setPadding(editText.getPaddingLeft(), editText.getPaddingTop(), editText.getPaddingRight(), editText.getPaddingBottom());
editText2.setId(View.generateViewId());
relativeLayout.addView(editText2);
return editText2;
}
Try FlowLayout in android and dynamiaclly inflate TextViews in it.
Rather than that you can use Linearlayout with fixed number of children in each row and if doing this the children must having same layout_weight.
But rather than going in such big disputes i will request you to simply replace RelativeLayout With FlowLayout in android
What you can try. Not sure, if it will work.
what you can do is calculate the width of screen on onCreate and make a check if the view exceeds that, make a new relative below the last one.
To be honest linear layout will be more easier to maintain using weight property.
I'm creating a number of edit texts next to each other programmatically using RelativeLayout. The default width of each edit text is wrap_content, but when the edit text reaches the edge of the screen, it visually changes it's sizes. So how can I make it move to the next line when this happens?
private EditText createEditText(EditText editText1, EditText editText2, String word){
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
editText.getLayoutParams().width,
editText.getLayoutParams().height
);
layoutParams.addRule(RelativeLayout.RIGHT_OF, editText1.getId());
layoutParams.addRule(RelativeLayout.BELOW, textView.getId());
layoutParams.leftMargin += 60;
editText2.setHint("" + word);
editText2.setHintTextColor(editText.getSolidColor());
editText2.setBackgroundResource(R.drawable.rounded_edittext);
editText2.setLayoutParams(layoutParams);
editText2.setPadding(editText.getPaddingLeft(), editText.getPaddingTop(), editText.getPaddingRight(), editText.getPaddingBottom());
editText2.setId(View.generateViewId());
relativeLayout.addView(editText2);
return editText2;
}
Try FlowLayout in android and dynamiaclly inflate TextViews in it.
Rather than that you can use Linearlayout with fixed number of children in each row and if doing this the children must having same layout_weight.
But rather than going in such big disputes i will request you to simply replace RelativeLayout With FlowLayout in android
What you can try. Not sure, if it will work.
what you can do is calculate the width of screen on onCreate and make a check if the view exceeds that, make a new relative below the last one.
To be honest linear layout will be more easier to maintain using weight property.
I am developing an app related to hindi kavita(poems). I want the poems to be displayed in the way real poems are displayed like the image shown below
Now the problem is I dont know how to use a textview to show this kind of text
Use a linear layout with vertical orientation. Add a text view for each line, with layout_width="match_parent" and the appropriate gravity attribute.
https://developer.android.com/reference/android/widget/LinearLayout.html
EDIT:
If you have your poem as an arraylist of strings where each element is a line of your poem, you can do:
//Initialise your layout in your activity onCreate()
LinearLayout layout = (LinearLayout) findViewById(R.id.linear_layout);
layout.setOrientation(LinearLayout.VERTICAL);
//Start listening to your firebase data and put this somewhere in the callback:
// poemLines is a list of Strings you get from firebase
for(i=0; i<poemLines.size(); i++){
TextView view = new TextView(context);
view.setText(poemLines.get(i));
//set any other attributes to your textview that you want, width, height, font, etc
view.setGravity(i%2==0?END:START);
layout.add(view);
}
>
Im displaying 13 cards dynamically by getting Resource as string and setting its margin in a layout but they are not setting up without overlapping. I tried a lot by changing margin but not working.
int counter=0;
forloop 1 to 13
int resID = getResources().getIdentifier(resourceName, "id", getPackageName());
im = (ImageView) findViewById(resID);
Context context = im.getContext();
cardID = context.getResources().getIdentifier(resourceName, "drawable", context.getPackageName());
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(im.getLayoutParams());
lp.setMargins(counter*30,0,0,0);//left,right,top,bottom
im.setLayoutParams(lp);
im.setImageResource(cardID);
counter++;
![Screen shot of 13 Cards ][2]
The issue is once you run out of horizontal space, you need to create a new row and add cards to that until that row runs out of space, etc.
A GridLayout would be better suited for what you're trying to accomplish. You could also use a GridView or TableLayout. It would be rather complicated to do this using a RelativeLayout since the child views need to be laid out in relation to each other, so you'd need to know exactly which view each child to the right of and which view it's below.
See this tutorial for an example of how to add views to a GridLayout dynamically:
http://android-er.blogspot.com/2014/09/insert-view-to-gridlayout-dynamically.html