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>
Related
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)
I would like to know how to add new strings at the bottom of a ScrollView every time I press a button.
For example at the beginning there is sentence1, press button, then sentence2 is under sentence1, press button, sentence3 is under sentence2, etc
I know how to make a scrollView and I have an array of strings to display:
final int[] sentences = new int[]{
R.String.sentence1,
R.String.sentence1,
R.String.sentence2,
R.String.sentence3,
R.String.sentence4
};
And I know how to make them appear one after another when a button is pressed (kind off replacing the previous one, like a TextSwitch but without the animation) :
if(nextSentenceId < sentences.length) {
officeOBSDialog.setText(sentences[nextSentenceId]);
++nextSentenceId;
}
Do you have any idea how I could manage to do that or what could I use? It occured to me that I could use like a layout inflator but I don't know how to put that to practice and where to put it. Thanks in advance
I recommend you to use ListView or RecyclerView.
https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView
However, if you consistently want to use ScrollView cause your screen UI is simple. You can simply wrap a LinearLayout with vertical orientation by a ScrollView.
activity.xml
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true">
<LinearLayout
android:id="#+id/lnContainer"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- your button declaration -->
</LinearLayout>
</ScrollView>
In your activity java file, add new row programmatically by:
private int position=0;
final int[] sentences = new int[]{
R.String.sentence1,
R.String.sentence1,
R.String.sentence2,
R.String.sentence3,
R.String.sentence4
};
//inside onCreate() method
yourButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View view){
TextView textView = new TextView(YourActivityClass.this);
textView.setText(sentences[position++]);
((LinearLayout)findViewById(R.id.lnContainer)).addView(textView);
}
});
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>
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.
I have been for hours trying to follow various tutorials in order to add items dynamically into a scrollview but nothing seems to be working...
The idea is just to add Strings into a TextView next to a Checkbox, which were done in a separate xml file and I just wanted the list to grow as I keep adding them.
For now, only one String is being added (the last one substitutes the previous one), and in any attempt to try to change that, my app stops working.
Here is the code as it stands:
TableLayout addPlayersTableLayout;
TableRow tableRow1;
ScrollView addPlayersScrollView;
String[] players = new String[]{ "Blah", "Whatever", "Test", "Nipah!"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPlayersTableLayout = (TableLayout)findViewById(R.id.TableLayout1);
tableRow1 =(TableRow)findViewById(R.id.tableRow1);
addPlayersScrollView = (ScrollView)findViewById(R.id.playersScrollView);
insertPlayerInScrollView();
}
Here is the implementation of the function that is supposed to add the items:
(add_player_row.xml is the file where the textview and checkbox that are supposed to be the items were made)
private void insertPlayerInScrollView() {
LayoutInflater inflator = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View newPlayerRow = inflator.inflate(R.layout.add_player_row, null);
TextView newPlayerTextView = (TextView) newPlayerRow.findViewById(R.id.addPlayerTextView);
CheckBox playerCheckBox = (CheckBox)findViewById(R.id.playerCheckBox);
newPlayerTextView.setText(players[1]);
addPlayersTableLayout.addView(newPlayerRow,0);
}
The final line of code is the only way it works at all, even though on most forums and tutorials, people would indicate for me to use the addPlayersScrollView, but if I do so, the app crashes.
So... Any ideas?
Thank you very much!
I'm facing something similar than you. I have a layout like this:
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:id="#+id/tableLayoutList"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
And have my row defined like this (mRowLayout.xml):
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayoutRow"
android:layout_width="match_parent"
android:layout_height="match_parent">
<CheckBox
android:id="#+id/checkBoxServEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</TableRow>
And then I use the following code to inflate my row:
private void fillTable(View v, Cursor c) {
TableLayout ll = (TableLayout) v.findViewById(R.id.tableLayoutList);
View mTableRow = null;
int i = 0;
while(!c.isAfterLast()){
i++;
mTableRow = (TableRow) View.inflate(getActivity(), R.layout.mRowLayout, null);
CheckBox cb = (CheckBox)mTableRow.findViewById(R.id.checkBoxServEmail);
cb.setText( c.getString(c.getColumnIndex(Empleado.EMAIL)));
mTableRow.setTag(i);
//add TableRows to TableLayout
ll.addView(mTableRow);
c.moveToNext();
}
}
What I'm trying to do here is inflate my rows dynamically. The cursor have the items that I wanna show from data base. I'm not sure if this can solve your problem. Let me know.