I created a cycle to make a Layout with a TextView for every unit in an Array:
for(int x = 0; x<coffeeSets.length; x++) {
final View view = getLayoutInflater().inflate(R.layout.custom_list, container);
TextView tv = (TextView) view.findViewById(R.id.tv1);
TextView tv2 = (TextView) view.findViewById(R.id.tv2);
tv.setText(coffeeSets[x].name);
tv2.setText(coffeeSets[x].price + "\u20BD");
}
Here is the xml of the custom layout, if that matters:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_marginTop="20dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:background="#color/white"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="15dp"
/>
<TextView
android:id="#+id/tv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginBottom="15dp"
android:layout_marginTop="15dp"
android:layout_marginRight="20dp"
/>
</RelativeLayout>
The problem is that it creates as many Layouts as I need, but it can only set the text for the first one:
The first layout gets the text of the last, and the last one gets empty
I understand that it because tv and tv2 are set to be 1st layout's textview, but how can I set text to other ones?
You can make inflate(R.layout.custom_list, container, false) and add the layout(container.addView(view);) manually, to appear on the screen. check below code.
The reason is if you set it to true or if you give only that layout it will be attached to the parent layout immediately, you cant add multiple items again because that view will already be added. For more detail about Inflator, you can read this article
final LinearLayout container = (LinearLayout) findViewById(R.id.container);
for(int x = 0; x<coffeeSets.length; x++) {
final View view = getLayoutInflater().inflate(R.layout.custom_list, container, false); // we can set attachToRoot as false
TextView tv = (TextView) view.findViewById(R.id.tv1);
TextView tv2 = (TextView) view.findViewById(R.id.tv2);
tv.setText(coffeeSets[x].name);
tv2.setText(coffeeSets[x].price + "\u20BD");
container.addView(view); // this you missed
}
Related
I want to create a scroll view list which would show "boxes" or more accurately custom made layouts (I'm using a custom class that extends a RelativeLayout - basically shows different pieces of information, some are static like places' working hours and some change dynamically and will be pulled from a server).
Though I encountered a problem - I (for the sake of seeing if my solution works) created 5 boxes and added them to the scroll view list but it seems like they are stacked upon each other. What's the proper way to make them appear one under another without manually tweaking their position coordinates? I was using addView() for that purpose but it doesn't work as intended for me or I use it poorly. If you know the answer, please briefly describe how this should be done.
Thanks in advance!
EDIT, here goes the code:
public class RestaurantBox extends RelativeLayout {
RestaurantBox (Context context){
super(context);
this.setBackgroundColor(context.getResources().getColor(R.color.colorAccent));
TextView restaurantName = new TextView(context);
restaurantName.setText("Test Restaurant");
RelativeLayout.LayoutParams restNameParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
this.addView(restaurantName, restNameParams);
restaurantName.setTypeface(null, Typeface.BOLD);
TextView freeSpots = new TextView(context);
freeSpots.setText("15/20");
RelativeLayout.LayoutParams freeSpotParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
freeSpotParams.topMargin = restNameParams.bottomMargin + 50;
this.addView(freeSpots, freeSpotParams);
TextView book = new TextView(this.getContext());
RelativeLayout.LayoutParams bookParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
book.setText("Book");
bookParams.setMargins(0,freeSpotParams.bottomMargin + 100,0,0);
this.addView(book, bookParams);
}
}
public class BrowseRestaurants extends AppCompatActivity {
int restaurantCount;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_browse_restaurants);
Intent intent = getIntent();
String login = intent.getStringExtra("LOGIN");
TextView text = (TextView) findViewById(R.id.txtWelcomeUser);
text.setText("Welcome, " + login);
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.relLayoutRestaurants);
RestaurantBox initRBox = new RestaurantBox(this);
initRBox.setTop(0);
initRBox.setBottom(300);
relativeLayout.addView(initRBox);
for(int i=1;i<5;i++){
final View view = relativeLayout.getChildAt(i-1);
RestaurantBox restaurantBox = new RestaurantBox(this);
restaurantBox.setTop(view.getBottom() + 50);
restaurantBox.setBottom(restaurantBox.getTop() + 300);
relativeLayout.addView(restaurantBox);
}
}
}
<!-- activity_browse_restaurants.xml-->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:orientation="vertical"
tools:context="com.konrad.rezerwacje1.BrowseRestaurants">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/scrollViewRestaurants"
android:layout_below="#+id/txtWelcomeUser"
android:layout_alignParentStart="true">
<RelativeLayout
android:id="#+id/relLayoutRestaurants"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="65dp"
android:orientation="vertical">
</RelativeLayout>
</ScrollView>
<TextView
android:id="#+id/txtLogout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/Logout"
android:textColor="#android:color/holo_red_dark"
android:textSize="18sp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true" />
<TextView
android:id="#+id/txtWelcomeUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="#style/TextAppearance.AppCompat.Display1"
android:textColor="#android:color/holo_blue_dark"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="9dp" />
</RelativeLayout
>
you are adding view in RelativeLayout so view stacking on each other so change it to LinearLayout in activity_browse_restaurants.xml
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/scrollViewRestaurants"
android:layout_below="#+id/txtWelcomeUser"
android:layout_alignParentStart="true">
<LinearLayout
android:id="#+id/relLayoutRestaurants"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="65dp"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
now make changes according to in BrowseRestaurants.class
replace
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.relLayoutRestaurants);
with
LinearLayout relativeLayout = (LinearLayout) findViewById(R.id.relLayoutRestaurants);
else will be fine if you want to change variable name its up to u, let me know if any problem
I have spent hours trying to figure this issue out and while I have come close, I am not getting the results I need. I have a messaging application that has a custom adapter and a listview with about 5 textviews. My issue is retrieving the text when a user long-presses on a message. After trying various methods, the closest I came was with:
mListView.setOnItemLongClickListener( new AdapterView.OnItemLongClickListener
(){
public boolean onItemLongClick(AdapterView<?> av, View v, int pos, long id) {
final String test = ((TextView)v).getText().toString();
Log.i(TAG, "Received: " + test);
return true;
}
});
The silly (read:frustrating) part about this code is that it works about 3-4 times successfully when clicked, however after that it force closes my application. The error I get is:
FATAL EXCEPTION: main
java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to android.widget.TextView
at android.widget.AbsListView.performLongPress(AbsListView.java:3347)
at android.widget.AbsListView$CheckForLongPress.run(AbsListView.java:3294)
at android.os.Handler.handleCallback(Handler.java:725)
The weird part is that I get the correct String of the message successfully the first few times, then it just doesn't want to work. After looking up the error, I tried cleaning the project multiple times, deleting the R.java file, and closing out Eclipse, but nothing has made a difference.
I have also tried using the position number of the messaging. The application never force closed when getting the position number of the message, however I couldn't get it to get the String that was attached to message at that location. The error was something about trying to convert from integer to string:
String test = ((EditText)av.getItemAtPosition(pos)).getText().toString();
My xml file consists of:
<?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:gravity="center_horizontal"
android:orientation="horizontal" >
<LinearLayout
android:id="#+id/left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_margin="20dip"
android:background="#drawable/bubble_yellow"
android:gravity="left"
android:orientation="vertical"
android:visibility="invisible" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
android:paddingBottom="1dip"
android:paddingLeft="15dip"
android:paddingRight="20dip"
android:paddingTop="1dip"
android:singleLine="false"
android:text="Large Text"
android:longClickable="true"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:gravity="right"
android:paddingRight="20dip"
android:longClickable="true"
android:text="TextView" />
</LinearLayout>
<LinearLayout
android:id="#+id/right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_margin="20dip"
android:background="#drawable/bubble_green"
android:orientation="vertical"
android:visibility="invisible" >
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="1dip"
android:paddingLeft="15dip"
android:paddingRight="20dip"
android:paddingTop="1dip"
android:singleLine="false"
android:longClickable="true"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:gravity="right"
android:longClickable="true"
android:paddingRight="20dip"
android:text="TextView" />
</LinearLayout>
</RelativeLayout>
Update 1: Added requested xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/background2"
android:orientation="vertical" >
<ListView
android:id="#+id/lv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:divider="#null"
android:dividerHeight="0dp"
android:longClickable="true"
android:stackFromBottom="true" >
</ListView>
<View
android:layout_width="match_parent"
android:layout_height="1dp" />
<LinearLayout
android:id="#+id/sendMsgLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="20dp"
android:orientation="horizontal" >
<EditText
android:id="#+id/messageText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:hint="Type Message"
android:inputType="textCapSentences|textMultiLine"
android:textColor="#FFFFFF"
android:maxLines="3" >
<requestFocus />
</EditText>
<ImageView
android:id="#+id/imageSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:src="#drawable/send512" />
</LinearLayout>
</LinearLayout>
Update2: My adapter contains the following:
ViewHolder viewHolder;
MessageModel array = data.get(position);
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = inflater.inflate(R.layout.message_item, null);
viewHolder.left =(LinearLayout)convertView.findViewById(R.id.left);
viewHolder.right =(LinearLayout)convertView.findViewById(R.id.right);
viewHolder.txt1 = (TextView) convertView
.findViewById(R.id.textView1);
viewHolder.txt3 = (TextView) convertView
.findViewById(R.id.textView3);
viewHolder.txt2 = (TextView) convertView
.findViewById(R.id.textView2);
viewHolder.txt4 = (TextView) convertView
.findViewById(R.id.textView4);
convertView.setTag(viewHolder);
Update 3: Tried my best to follow #MDragon00's advice, unfortunately my app is still crashing when long pressing. I now have:
mListView.setOnItemLongClickListener( new AdapterView.OnItemLongClickListener
(){
public boolean onItemLongClick(AdapterView<?> av, View v, int pos, long id) {
TextView textView1 = (TextView) v.findViewById(R.id.textView1);
TextView textView2 = (TextView) v.findViewById(R.id.textView2);
TextView textView3 = (TextView) v.findViewById(R.id.textView3);
TextView textView4 = (TextView) v.findViewById(R.id.textView4);
View.OnLongClickListener listener = new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
TextView textView = (TextView) v;
String text = textView.getText().toString();
Log.i(TAG, "Text Selected = " + text);
return false;
}
};
textView1.setOnLongClickListener(listener);
textView2.setOnLongClickListener(listener);
textView3.setOnLongClickListener(listener);
textView4.setOnLongClickListener(listener);
return true;
}
});
}
The description of what each parameter does in onItemLongClick: http://developer.android.com/reference/android/widget/AdapterView.OnItemLongClickListener.html
The issue here is that av is the entire ListView, while v is the entire row. Your row doesn't simply consist of a TextView, so you can't cast it to a TextView. In other words,
final String test = ((TextView)v).getText().toString();
isn't a good idea as the parent view is a RelativeLayout. A better solution would be to do the following:
TextView textView = (TextView) v.findViewById(R.id.idOfTextView);
String text = textView.getText().toString();
As a small side suggestion, it sounds like you want to simply click on the item, not long click it. Use an OnItemClickListener instead of a OnItemLongClickListener if it suits your needs.
Edit:
According to your comments, the user will click/tap on a certain TextView out of several TextViews within some abstract row, and you want to get one of those four TextViews.
To do so, you'll need a new listener on each TextView. I can't give an exact answer without seeing your adapter, but when you inflate/get the row view to give to the ListView in the adapter, set an OnClickListener to the TextViews. For example with some pseudo-code:
// Get the textViews, to assign a listener to them
TextView textView1 = (TextView) v.findViewById(R.id.textView1);
TextView textView2 = (Textview) v.findViewById(R.id.textView2);
..... // Etc and so on
// Create this listener anywhere, including via making the adapter/class
// implement the listener and passing it in instead
View.OnClickListener listener = new View.OnClickListener(
#Override
public void onClick(View v) {
// Get the view as a TextView, as this will only be used
// with TextViews, so the only view to be passed
// will be Textviews
TextView textView = (TextView) v;
// Do whatever with that text, or however you want to use the view
String text = textView.getText().toString();
someFunction(text);
}
);
textView1.setOnClickListener(listener);
textView2.setOnClickListener(listener);
..... // Etc and so on
Now then, if you need the exact row that was clicked AND the text from an exact TextView, then you'll need to use both of the listeners [ie, one on the ListView and ones on the TextViews] to get the appropriate data.
Edit Hopefully Final:
public class TestAdapter extends BaseAdapter {
Context mContext;
public TestAdapter (Context context, Data someData) {
this.mContext = context;
// Set up the data for your listView however
}
#Override
public int getCount() {
return howManyRows;
}
#Override
public Object getItem(int position) {
return objectAtPosition;
}
#Override
public long getItemId(int position) {
return 0;
} // Unnecessary, unless using databases
// The listener for the textViews, feel free to use different listeners
View.OnClickListener TextViewListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// Get the view as a TextView, as this will only be used
// with TextViews, so the only view to be passed
// will be Textviews
TextView textView = (TextView) v;
// Do whatever with that text, or however you want to use the view
String text = textView.getText().toString();
someFunction(text);
}
};
// Using the efficient pattern for recycling the views rather than using
// findViewById repeatedly
public static class ViewHolder{
public TextView textView1;
public TextView textView2;
public TextView textView3;
public TextView textView4;
// And any other view that's part of the row view that you need
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = null;
ViewHolder holder;
if(convertView == null) {
// Then gotta set up this row for the first time
LayoutInflater inflater =
(LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.row_layout.xml, parent, false);
// Create a ViewHolder to save all the different parts of the row
holder = new ViewHolder();
holder.textView1 = (TextView) row.findViewById(R.id.textView1);
holder.textView2 = (TextView) row.findViewById(R.id.textView2);
holder.textView3 = (TextView) row.findViewById(R.id.textView3);
holder.textView4 = (TextView) row.findViewById(R.id.textView4);
// Make the row reuse the ViewHolder
row.setTag(holder);
}
else { // Otherwise, use the recycled view
row = convertView;
holder = (ViewHolder) row.getTag();
}
// Set the current row's Textview onClickListeners
// Note: You MAY be able to only set these once- feel free to set that
holder.textView1.setOnClickListener(TextViewListener);
holder.textView2.setOnClickListener(TextViewListener);
holder.textView3.setOnClickListener(TextViewListener);
holder.textView4.setOnClickListener(TextViewListener);
// Set up the rest of the views however you need
/*.....
......
*/
return row;
}
}
getItemAtPosition(pos) returns the view used as each of the item in the listView. According to your xml, the root element is RelativeLayout, so this method will return an RelativeLayout, not a TextView.
what you can do is:
String test = ((TextView)((View)av.getItemAtPosition(pos)).findViewById(R.id.textView1))
.getText().toString();
I have Vertical ScrollView where I am going to add some Views after a buttonClick. Here is the xml of the scroll view
<ScrollView
android:background = "#drawable/border"
android:layout_weight="31"
android:id="#+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="0dp" >
<LinearLayout
android:id="#+id/layoutScroll"
android:padding = "10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/layoutContainer"
android:padding="5dp"
android:orientation="vertical"
android:background="#drawable/border_2"
android:layout_width="fill_parent"
android:layout_height = "wrap_content">
<RelativeLayout
android:id="#+id/relativeLayout"
android:layout_height = "wrap_content"
android:layout_width = "fill_parent">
<TextView
android:id="#+id/textWord"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/word"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/textNumber"
android:background = "#drawable/border_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text=" 1 "
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
<EditText
android:id="#+id/editWord"
android:layout_marginTop="3dp"
android:layout_gravity="left"
android:inputType="text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:lines="1"
android:scrollbars="horizontal"/>
<TextView
android:id="#+id/textDefinition"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text = "#string/definition" />
<EditText
android:id="#+id/editDefinition"
android:gravity="top|left"
android:inputType="textMultiLine"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:lines="3"
android:maxLines="3"
android:scrollbars="vertical"/>
</LinearLayout>
<TextView
android:id="#+id/textEmpty"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:lines="1"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
</ScrollView>
In this function I create the same objects for adding them to the LinearLayout
private void initInterface (){
layoutScroll = (LinearLayout) findViewById (R.id.layoutScroll);
layoutContainer = new LinearLayout(getApplicationContext());
relativeLayout = new RelativeLayout(getApplicationContext());
textWord = new TextView(getApplicationContext());
textDefinition= new TextView(getApplicationContext());
textNumber = new TextView(getApplicationContext());
textEmpty = new TextView(getApplicationContext());
editWord = new EditText(getApplicationContext());
editDefinition = new EditText(getApplicationContext());
layoutContainer.setPadding(5, 5, 5, 5);
layoutContainer.setOrientation(LinearLayout.VERTICAL);
layoutContainer.setBackgroundResource(R.drawable.border_2);
LinearLayout.LayoutParams param1 =
new LayoutParams(LayoutParams.MATCH_PARENT , LayoutParams.WRAP_CONTENT );
layoutContainer.setLayoutParams(param1);
RelativeLayout.LayoutParams param2 =
new RelativeLayout.LayoutParams (RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
relativeLayout.setLayoutParams(param2);
textWord.setLayoutParams(param2);
textWord.setTextAppearance(this,android.R.style.TextAppearance_Medium);
textWord.setText("Word:");
RelativeLayout.LayoutParams param3=
new RelativeLayout.LayoutParams
(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
param3.addRule(RelativeLayout.ALIGN_PARENT_TOP);
param3.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
textNumber.setBackgroundResource(R.drawable.border_1);
textNumber.setTextAppearance(this,android.R.style.TextAppearance_Medium);
textNumber.setLayoutParams(param3);
relativeLayout.addView(textWord);
relativeLayout.addView(textNumber);
LinearLayout.LayoutParams param4 = param1;
param4.setMargins(0, 3, 0, 0);
editWord.setGravity(Gravity.LEFT);
editWord.setTextAppearance(this,android.R.style.TextAppearance_Medium);
editWord.setLines(1);
editWord.setHorizontallyScrolling(true);
editWord.setLayoutParams(param4);
textDefinition.setLayoutParams(param1);
textDefinition.setTextAppearance(this,android.R.style.TextAppearance_Medium);
textDefinition.setText("Definition:");
editDefinition.setGravity(Gravity.TOP | Gravity.LEFT);
editDefinition.setSingleLine(false);
editDefinition.setLayoutParams(param1);
editDefinition.setMaxLines(3);
editDefinition.setLines(3);
editDefinition.setVerticalScrollBarEnabled(true);
editDefinition.setImeOptions(EditorInfo.IME_FLAG_NO_ENTER_ACTION);
textEmpty.setTextAppearance(this,android.R.style.TextAppearance_Medium);
textEmpty.setLines(1);
textEmpty.setLayoutParams(param1);
layoutContainer.addView(relativeLayout);
layoutContainer.addView(editWord);
layoutContainer.addView(textDefinition);
layoutContainer.addView(editDefinition);
}
And then I add them to the Layout like this.
public void onCLick_Add(View v){
layoutScroll.addView(layoutContainer);
layoutScroll.addView(textEmpty);
}
The problem is that It only workd once . When I click the button for the second time the app crashes.
Thank you in advance.
Your log says:
Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
You are trying to add same layoutContainer and textEmpty multiple times when clicking multiple times. This fails because they are already added and therefore already have a parent. (You cannot add same View to more then one parent)
Solution
I guess you want to create a new View every time you press the button and add this to your layoutScroll. You should call your init-method again for every click:
public void onCLick_Add(View v){
initInterface();
layoutScroll.addView(layoutContainer);
layoutScroll.addView(textEmpty);
}
I would also suggest to divide initInterface() into:
private View createLayoutContainer();
private View createTextEmpty();
Make sure you take initialization of scrollView outside (e.g. onCreate) and you declare views like layoutContainer localy in the createLayoutContainer() instead of globally.
Here a snippet how it would look:
private View createLayoutContainer(){
LinearLayout layoutContainer = new LinearLayout(getApplicationContext());
RelativeLayout relativeLayout = new RelativeLayout(getApplicationContext());
TextView textWord = new TextView(getApplicationContext());
...
return layoutContainer;
}
public void onCLick_Add(View v){
layoutScroll.addView(createLayoutContainer());
layoutScroll.addView(createTextEmptyView());
}
The problem occurs due to the fact that a ScrollView can only have on child View. In other words, a ScrollView can have a LinearLayout or a RelativeLayout or a TextView etc. Update your code such that new views inside are added inside LinearLayout (layoutScroll) instead of ScrollView.
As I pointed out in the comment, the bug is this : Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
Checklist for these kind of bugs.
As pointed out in this post the specified child already has a parent
Double check all your addView calls.
Make sure not to add any view more then once. When a View is allready
used (e.g., you got it with findViewById, don't use addView on it.
When you want to add a view, use addView with a NEW view. You can add
several of these new views to one view, but you cannot add that one
view multiple times.
You can't re-use a view simply by changing some
stuff. You CAN re-use a variable, but you need to make a new view if
you want to re-add it using addView.
I made a custom xml that has a LinearLayout with the layout_margins set. If i view the graphic layout it shows the margins, but in another activity when i try to add this view to a LinearLayout within a ScrollView none of the margins are there. Here's the custom xml code....
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#drawable/run_background"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="5dp">
<TextView
android:id="#+id/tvRunName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_gravity="center"
android:layout_marginTop="10dp" />
Here's the code that adds the view....
for(int x = 0; x < runs.size(); x++){
inflater = (LayoutInflater)this.getSystemService(this.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.run_layout, null);
TextView name = (TextView) layout.findViewById(R.id.tvRunName);
name.setText(runs.get(x).getName());
llRuns.addView(layout);
}
How can i have the views spaced out like i want?
The LayoutParams are not being included while inflating the layout. Try adding a third parameter while inflating the layout:
View layout = inflater.inflate(R.layout.run_layout, null, false);
I have a view, inflated from custom layout, which contains a TextView.
I tried to set TextView text both from xml via string resource and programmatically after layout inflating - I'm still getting only android.widget.RelativeLayout#4166f2d8 instead of normal text. What am I doing wrong?
Xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layers_list_item_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp" >
<CheckBox
android:id="#+id/layers_list_item_switch"
blablabla... />
<TextView
android:id="#+id/layers_list_item_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:layout_toLeftOf="#id/layers_list_item_switch"
android:selectAllOnFocus="true"
android:text="#string/layers_list_default_text"
android:ellipsize="marquee"
android:focusable="true"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:scrollHorizontally="true"
android:textColor="#android:color/black"
android:textSize="16sp"
android:textStyle="bold"
android:typeface="serif"
android:clickable="true" />
</RelativeLayout>
View inflating method:
public View createLayerListItem (String text) {
View v = View.inflate(this, R.layout.layers_list_item, null);
TextView text_view = (TextView) v.findViewById(R.id.layers_list_item_text);
text_view.setText(text);
return v;
}
And this views are used to fill some ListView:
ListView layers_list = (ListView)layers_dialog.findViewById(R.id.layers_list);
ArrayAdapter<View> adapter = new ArrayAdapter<View>(this, R.layout.layers_list_item, R.id.layers_list_item_text);
adapter.add(createLayerListItem("Test 1"));
adapter.add(createLayerListItem(""));
adapter.add(createLayerListItem("Very very very very very very long line"));
All my TextViews are wrong, showing android.widget.RelativeLayout#4166f2d8. I also tried to use default text from xml, not changing it from code at all - still I didn't got my text from resource, only address.
Array adapter convert your views to string array because of this, it set textview text as its class name. So you should use like below,
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.layer_list_item, R.id.layers_list_item_text);
adapter.add(createLayerListItem("Test 1"));
adapter.add(createLayerListItem("Test 2"));
adapter.add(createLayerListItem("Test 3"));
public String createLayerListItem(String text) {
View v = View.inflate(this, R.layout.layer_list_item, null);
TextView text_view = (TextView) v
.findViewById(R.id.layers_list_item_text);
text_view.setText(text);
return text_view.getText().toString();
}