Create multiple dynamic TextView with same style declared in xml - java

I want to create multiple dynamic TextView but I need them to look the same way as one of the TextView that already style in xml. How can I do that?
For example I want all the dynamic created TextView to have same attribute as the main one:
<TextView
android:id="#+id/mainTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/colorPrimary"
android:gravity="center_vertical"
android:padding="14dp"/>

You can implement this by using this:
Take a parent Linearlayout with the orientation vertical
LinearLayout parentView= findViewById(R.id.parentView);
code to add the views:
for(int i = 0; i < /*No of views*/; i++) {
View itemView = LayoutInflater.from(this).inflate(R.layout.catagoryitem, parentView, false);
parentView.addView(itemView);
}
Here catagoryitem is the TextView with style xml file.

Related

How to make Views iterating on data objects (without ListView / RecyclerView)?

I am trying to spawn some XML view for each instance of POJO data objects in a list, similar to how a ListView would do it, but it's not a ListView actually, but an empty LinearLayout instead, which is inside a ScrollView below other Fragment's content.
This is the item.xml file I want to inflate for each element of the list:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/item_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="0dp"
android:text="ITEM_LABEL"
android:textSize="16sp" />
<TextView
android:id="#+id/item_text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="4dp"
android:text="ITEM_TEXT_1"
android:textSize="14sp" />
<TextView
android:id="#+id/item_text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="4dp"
android:text="ITEM_TEXT_2"
android:textSize="14sp" />
</LinearLayout>
...and this is the way I am trying to inflate it in the Fragment Java class:
public class MyFragment extends Fragment {
// we skip the "boilerplate"...
// [...]
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.my_fragment, container, false);
// XXX I use LiveData<> with Room to retrieve
// rows from DB inside POJO objects
LiveData<List<MyItem>> items_list = itemsViewModel.getItemsByParentId(some_id);
// The "parent" is not relevant, let's just
// focus on the List
LinearLayout items_list_layout = view.findViewById(R.id.items_list_layout);
items_list.observe(getActivity(), new Observer<List<MyItem>>() {
#Override
public void onChanged(List<MyItem> items) {
// Just in case, (maybe I'm wrong but) I think otherwise
// previous inflated objects remain on loading this same
// fragment for another parent
objs_list_layout.removeAllViews()
for (MyItem item : items) {
// XXX Here I inflate item.xml as a LinearLayout
LinearLayout obj_item = (LinearLayout) View.inflate(view.getContext(), R.layout.item, items_list_layout);
// XXX ... and try to change it's TextView children
TextView item_label = obj_item.findViewById(R.id.item_label);
item_label.setText(item.item_label);
TextView item_text1 = obj_item.findViewById(R.id.item_text1);
item_text1.setText(item.item_text1);
TextView item_text2 = obj_item.findViewById(R.id.item_text2);
item_text2.setText(item.item_text2);
}
}
});
}
}
This works well when the method getItemsByParentId only return a List with one only MyItem instance. But when the query returns more than one Item, it works unexpectedly wrong:
The first inflated item.xml element (or the one shown first, on top) has its TextViews modificated as expected, but for the last item in the list.
The rest of "inflated elements" have not been changed (it shows just ITEM_LABEL, ITEM_TEXT1 and ITEM_TEXT2 hardcoded strings as they are in the template XML file).
However, it inflates the XML template items.size() times as I planned.
Actually, the objective is that each "inflated item.xml" is edited with attributes of each corresponding Item. Just like a ListView would do, but without using ListView at all, because the goal is, actually, bloating an existing ScrollView (the main container in the fragment) that shows other different Views outside of the "LinearLayout" dedicated to generate this "list". How can I make it work without these errors?
View.inflate imho is a not the clearest method ) it returns the root View of the inflated hierarchy. If root was supplied, this is the root View; otherwise it is the root of the inflated XML file.
So obj_item is not an item view. It is an items_list_layout view. Inside it you find R.id.item_label in first item view and set it. Other item views are not initialized because findViewById returns first item it found.
Change this part:
LinearLayout obj_item = (LinearLayout) View.inflate(view.getContext(), R.layout.item, items_list_layout);
to
LinearLayout obj_item = LayoutInflator.from(view.getContext()).inflate(R.layout.item, items_list_layout, false);
I prefer to add child views explicitly to make code more readable. So and add this code to add item view to parent layout:
items_list_layout.addView(obj_item)

Programmatically add an ImageView to Layout

I'm trying to add a bunch of ImageView on my UI using a loop, the problem is that I have no Idea if the ImageView is being added or not because when I run the app it just gives me a blank white screen.
for(int i = 0; i < jsonArray.length(); i++) {
Log.d("test", "ok"); //the loop works btw
poster.setId(i);
JSONObject jsonObject = jsonArray.getJSONObject(i);
ImageView poster = new ImageView(getApplicationContext());
poster.setBackgroundResource(R.drawable.myPoster);
RelativeLayout.LayoutParams posterParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
);
posterParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
posterParams.addRule(RelativeLayout.CENTER_VERTICAL);
posterParams.width = 160; //is this DP?
posterParams.height = 220;
relativeLayout.addView(poster, posterParams);
}
Any suggestion is welcome.
EDIT
I added another piece of code just to test if a widget will be added without using a loop:
//test
LinearLayout layout = new LinearLayout(this);
Button btn = new Button(this);
btn.setText("this is a button");
btn.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
layout.addView(btn);
And I still get the same result, just blank.
First of all, you are giving exactly the same parameter to each ImageView this causes all your ImageView lays on Like STACK only the last one will be visible to you. You may use ScrollView to see if the ImageViews actually added to your root layout
Secondly, set layout parameters to your dynamic ImageViews not your root layout.
Update
How to use ScrollView,
First of all, your XML should contain ScollView and a child (LinearLayout in our case but you can choose any layout depending on your use case) for placing your ImageView
<ScrollView>
<LinearLayout
android:id = "imageViewPlaceHolder">
</LinearLayout>
</ScrollView>
Secondly, in your Java code, you should find an inner layout to add views as follows
LinearLayout placeHolder = findViewById(R.id.imageViewPlaceHolder);
Then you are ready to add ImageViews into placeHolder since your placeHolder wrapped with ScrollView it will create a scroll dynamically if the content height goes beyond the dedicated height.
placeHolder.addView(yourImageView);
Adding everything from Java
HorizontalScrollView hsv = new HorizontalScrollView(context);
hsv.setLayoutParams(yourLayoutParams);
LinearLayout myPlaceHolder = new LinearLayout(context);
myPlaceHolder.setLayoutParams(yourLayoutParamsForLinearLayout);
myPlaceHolder.addView(yourDesiredImageView);
hsv.addView(myPlaceHolder);
yourRootLayout.addView(hsv);
Hope it makes sense, feel free to ask any clarification
try this:
listView = (ListView) findViewById(R.id.lv_info);
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, text);
listView.addHeaderView(creatHeader(getString(R.string.abuot_email),getResources().getString(R.string.email_info)));
listView.addHeaderView(creatHeader(getString(R.string.about_phone),getResources().getString(R.string.admin_phone_num)));
listView.addHeaderView(creatHeader(getString(R.string.about_copyright), getResources().getString(R.string.copyright_info)));
listView.addHeaderView(creatHeader(getString(R.string.about_version),getResources().getString(R.string.version_info)));
listView.setAdapter(adapter);
Method creatHeader:
public View creatHeader(String title, String text) {
View v = getLayoutInflater().inflate(R.layout.lv_item_header_info, null);
((TextView) v.findViewById(R.id.tvTitle)).setText(title);
((TextView) v.findViewById(R.id.tvText)).setText(text);
return v;
}
Layout file for items:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/activity_vertical_margin">
<TextView
android:id="#+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ssss"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"/>
<TextView
android:id="#+id/tvText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="sssssssss"
android:gravity="center_vertical"/>
</LinearLayout>

Android textView.setText() throws exception

I'm trying to create an app where I can put several times the same kind of layout in a LinearLayout.
The layout just has a TextView and i'm trying to use setText but this line of code doesn't seems to work.
I don't know how many layout I must add to the LinearLayout because it depends of how many drones (I have one layout/drone) the user will have upload to the app, so I made a function that read the text to put in the TextView from a SharedPreference and that also read the number of drones (so the number of layouts) in another SharedPreferences.
The TextView i'im putting the string in is from a layout named dronelayoutmain.
I tried sending just "test" in the setText, but it crashes anyway, so I think that android just can't find my TextView, but I don't really know why.
So here is the function I call in OnCreate that is supposed to add one layout for each drone I have
public void affichagedrone(){
LinearLayout mlineairelayout = (LinearLayout)
findViewById(R.id.lineaireLayout);
LinearLayout.LayoutParams params = new
LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
Context mContext;
mContext = getApplicationContext();
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
SharedPreferences droneprefs = mContext.getSharedPreferences("dronepref", MODE_PRIVATE);
SharedPreferences applimaindata = mContext.getSharedPreferences("applimaindata", MODE_PRIVATE);
int nbdrone = applimaindata.getInt(String.valueOf(emplacementNbDrone),1);
String string;
TextView textViewnomConstructeurDrone;
if (nbdrone !=0) {
for(int i=0;i<nbdrone;i++) {
textViewnomConstructeurDrone = (TextView) findViewById(R.id.textViewNomConstructeur);
string = droneprefs.getString(String.valueOf(i),"Fail");
textViewnomConstructeurDrone.setText(string);
final View rowView = inflater.inflate(R.layout.dronelayoutmain, null);
// Add the new row before the add field button.
mlineairelayout.addView(rowView);
}
}
}
And here is the layout i'm trying to put in the LinearLayout.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="120dp"
>
<TextView
android:id="#+id/textViewNomConstructeur"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:text="#string/adddrone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
The function is supposed to check in applimaindata the number of layout to add, and then, in the for(), is supposed to set the Text of the TextView from the droneprefs file and then add the Layout to the main LinearLayout
If this TextView belongs in the newly inflated layout, you must find it after the layout is inflated:
for(int i = 0; i < nbdrone; i++) {
final View rowView = inflater.inflate(R.layout.dronelayoutmain, null);
textViewnomConstructeurDrone = rowView.findViewById(R.id.textViewNomConstructeur);
string = droneprefs.getString(String.valueOf(i),"Fail");
textViewnomConstructeurDrone.setText(string);
mlineairelayout.addView(rowView);
}

How to add Strings to a TextView / ScrollView?

I am quiet new to android developing sorry!
I want to add doctor values as Strings (first name, last name, and some others later) as one entry (I was trying to do so with Objects) to my Scroll View via a button. I know that I need a Layout and a Text View to do so but my Virtual Machine crushes.
As far as I understand I have to put my Text View (with the Strings) in the Layout and the Layout in the Scroll View (am I wrong?).
I was trying several things from different websites which all provide similar solutions but nothing worked so far. I am using Android 6.0 with android studio and designed my UI with the Design View and adapted some code in the XML files.
public void addDoctor(View view) {
setContentView(R.layout.activity_main);
// standard java class Doctor
Doctor doc = new Doctor("Foo", "Boo");
// this is the ScrollView I generated with the design
ScrollView sv = (ScrollView) this.findViewById(R.id.ScrollViewDoctor);
TextView tv = new TextView(this);
// trying to fix the parent problem here
if(tv.getParent() != null) {
((ViewGroup)tv.getParent()).removeView(tv); // <- fix
}
//this should be "Foo"
tv.setText(doc.getDocName());
// this is the layout I generated with the design "linlay"
LinearLayout ll = (LinearLayout) this.findViewById(R.id.linlay);
sv.addView(ll);
//only one child object! -> in the error log
ll.addView(tv);
setContentView(view);
}
I expected the Strings of the object to appear in the Scroll View but the error log says that "ScrollView can host only one direct child" which I was trying to fix with the if statement but it does not seem to affect my code.
Can you please help me with this. Do I miss something?
Thank you!
As far as I understand I have to put my Text View (with the Strings) in the Layout and the Layout in the Scroll View (am I wrong?).
You've right.
<ScrollView>
<LinearLayout>
<TextView></TextView>
</LinearLayout>
</ScrollView>
How to Add a doctor in the right way
error log says that "ScrollView can host only one direct child"
You're getting the error because you added already the linear layout inside the <ScrollView>, so you don't have to call, sv.addView(ll); because it's already inside (And you cannot add multiple layout in standard ScrollView)
So you're reference to ScrollView it's useless.
if you're xml is like this:
<ScrollView>
<LinearLayout>
</LinearLayout>
</ScrollView>
You can achieve your result with this:
public class MyActivityDoctors extends Activity {
ScrollView sv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sv = (ScrollView) this.findViewById(R.id.ScrollViewDoctor);
}
public void addDoctor(Doctor doctor)
{
//Linear Layout inside your ScrollView
LinearLayout ll = (LinearLayout) this.findViewById(R.id.linlay);
//Create a new TextView with doctor data
TextView tv = new TextView(this);
tv.setText(doctor.getDocName());
//Adding textView to LinearLayout
ll.addView(tv);
}
}
remove setContentView(view); on the end, you have already set this layout in first line
setContentView in most cases should be called once, inside onCreate method. if you are calling setContentView multiple times you are basically overrriding previous one
also this
if(tv.getParent() != null) {
((ViewGroup)tv.getParent()).removeView(tv); // <- fix
}
is unnecessary, you are creating new TextView line above, it wont have parent for shure
Why don't you use a RecyclerView? And then you don't need a ScrollView. And don't call setContentView(view); multiples times. You have to do only 1 time.
you need to create Multiline TextView
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="20dp"
android:fillViewport="true">
<TextView
android:id="#+id/txtquestion"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:background="#drawable/abs__dialog_full_holo_light"
android:lines="20"
android:scrollHorizontally="false"
android:scrollbars="vertical"
android:textSize="15sp" />
</ScrollView>

Inflate TextViews to LinearLayout

I want to inflate TextViews to LinearLayout.
I have a layout activity_play_game and java class PlayGameActivity.
Currently, for hardcoded number of TextViews it looks like this:
Now I tried to add number of TextViews according to the value of variable numberForbiddenWords. I added a piece of code that looks like this:
LinearLayout playGame = (LinearLayout) findViewById(R.id.activity_play_game);
TextView temp;
TextView[] textViews = new TextView[numberForbiddenWords];
for(int i = 0; i < numberForbiddenWords; i++) {
temp = new TextView(this);
playGame.addView(temp);
textViews[i] = temp;
}
And I have a method that adds textViews to the activity_play_game. Unfortunately now it looks like this:
As you can see it added TextViews at the bottom. So I removed all TextViews from activity_play_game and added LinearLayout to inflate TextViews:
How can I inflate TextViews to this LinearLayout above the buttons?
I found that kind of solution:
activity_to_add_words:
<?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:orientation="vertical">
<TextView
android:id="#+id/textout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
In the java class:
final View addView;
LayoutInflater layoutInflater = (LayoutInflater) getBaseContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
addView = layoutInflater.inflate(R.layout.activity_to_add_words,
null);
final TextView textOut = (TextView) addView.findViewById(R.id.textout);
but this is for a View, not TextView. Do you know how to do it?
Get reference of your LinearLayout container_blue and add TextView's to it.
Try this:
LinearLayout playGame = (LinearLayout) findViewById(R.id.container_blue);
TextView temp;
TextView[] textViews = new TextView[numberForbiddenWords];
for(int i = 0; i < numberForbiddenWords; i++) {
temp = new TextView(this);
temp.setText("TextView " + String.valueOf(i));
temp.setId(i);
temp.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
playGame.addView(temp);
textViews[i] = temp;
}
make one layout file using textview like this :
layout_textview.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="#+id/txt_spin"
android:textSize="18sp"
android:background="#fff"
android:padding="5dp"
android:textColor="#000"
android:layout_height="wrap_content"/>
then apply following code in your java file:
LinearLayout playGame = (LinearLayout) findViewById(R.id.container_blue);
LayoutInflater li =(LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = li.inflate(R.layout.layout_textview, null);
TextView txt= (TextView) view.findViewById(R.id.txt_spin);
playGame.addView(view);
Hope it works for you...happy coding..:)
As far as I see your initial problem was about adding the items dynamically before the three buttons. If you want to add them before the three buttons simply call playGame.addView(temp,0); This will always add the item to the first position in the layout.
If you need a specific order of the added views you need to play with the for loop to add them in the right order.

Categories

Resources