I've been struggling with finding an appropiate answer on how to add components to a layout in a fragment at runtime in android studio.
Specifically:
I have Class A which downloads and parses an XML file. Fragment B instantiates this Class A and should display those downloaded items. (just a textview for now)
This is the XML file in which the textView should be displayed. The items should be displayed in two columns. I know how to create the layout in the XML File but I have no idea on how to do it programatically. I've also read something about inflaters but I dont know if it fits this purpose.
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TableRow
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingTop="10dp">
<TextView
android:id="#+id/columnItem"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:layout_marginStart="5dp"
android:layout_weight=".5"
android:background="#c5c5c5"
android:gravity="center"
android:text="#string/CategoryLeft" />
</TableRow>
</ScrollView>
</TableLayout>
So here is the Code in Fragment B which currently just changes the text of the two existing textviews, that works just fine.
public void onStart() {
super.onStart();
ArrayList<String> categories = new ArrayList<>();
XMLHandler getXML = new XMLHandler();
getXML.execute();
categories = getXML.getCategories();
Iterator<String> it = categories.iterator();
while (it.hasNext()) {
System.out.println("Data is " + it.next());
columnItem.setText(it.next());
}
}
The goal is to add a new TextView for each iteration through the while loop to the parent layout. This TextView should display the content of it.next().
Thanks in advance and let me know if u need any further information.
If you want to add a TextView to TableRow.
First, add an id to TableRow
<TableRow
android:id="#+id/table1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingTop="10dp">
Then, in your onCreate
tableRow = findViewById(R.id.table1); // tableRow is a global variable
add a void in your fragment
private void addTextView(String atext) {
TextView txt = new TextView(getActivity());
txt.setText(atext);
tableRow.addView(txt);
// here you can add other properties to the new TextView (txt)
}
and then
public void onStart() {
super.onStart();
ArrayList<String> categories = new ArrayList<>();
XMLHandler getXML = new XMLHandler();
getXML.execute();
categories = getXML.getCategories();
Iterator<String> it = categories.iterator();
while (it.hasNext()) {
String atxt = it.next();
System.out.println("Data is " + atxt);
addTextView(atxt);
}
}
Related
I am trying to create a LinearLayout programmatically from information contained in an Array.
Let me explain :
I create a professional application that will not be on PlayStore.
I have the following Array, manually populated, (a kind of global variable):
static final String[][] reseaux = new String[][] {
{"Net1","192.168.0.1"},
{"Net2","192.168.10.1"},
{"Net3","192.168.20.1"},
{"Net4","192.168.30.1"}
};
For some customers, it contains only one entry :
static final String[][] reseaux = new String[][] {
{"Net1","192.168.0.1"}
};
According to the Array containing only one entry, I created the following layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/welcome"
android:layout_gravity="center"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:ignore="Overdraw">
<include
android:id="#+id/tool_bar"
layout="#layout/tool_bar" />
<ScrollView
android:layout_height="match_parent"
android:layout_width="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="#+id/linearLayout"
android:layout_marginTop="15dp"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false">
<LinearLayout
android:id="#+id/linearLayoutTest"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
And the code :
LinearLayout l = findViewById(R.id.linearLayoutTest);
for (int i = 0; i < reseaux.length; ++i) {
final int id = i;
ImageButton resBtn = new ImageButton(this);
TextView tv = new TextView(this);
tv.setGravity(Gravity.CENTER | Gravity.BOTTOM);
tv.setText(reseaux[i][0]);
resBtn.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.button_reseaux));
resBtn.setBackgroundColor(getResources().getColor(R.color.transparent));
l.addView(resBtn);
l.addView(tv);
resBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Check network
if (CheckNetworkStatus.isNetworkAvailable(getApplicationContext())) {
Intent i = new Intent(getApplicationContext(),
HomeReseauActivity.class);
startActivity(i);
BASE_URL = null;
nomReseau = null;
BASE_URL = reseaux[id][1];
nomReseau = reseaux[id][0];
} else {
//Error message if no network connexion
if (toastMessage != null) toastMessage.cancel();
toastMessage = Toast.makeText(HomeActivity.this, getString(R.string.networkError), Toast.LENGTH_LONG);
toastMessage.show();
}
}
});
Give me the following result that suits me perfectly :
Now, when I have multiple entries in my Array, here's what I get :
This does not suit me. I will like horizontal lines of three icons. When a line is filled, it creates a new line of three icons, etc.
Here is a quick edit with paint to demonstrate what I want:
I think the solution must be simple .. but I can not get this result.
Be indulgent with my code, I learn everything by myself and there is surely a better way to write :-)
Hoping someone can help me!
As stated in the comments of my question, the solution was to use RecyclerView and GridLayoutManager.
For future readers, this link has helped me a lot!
Thanks to everyone who answered my question.
Please bear with me as I am new to the use of Views and Layouts.
I am trying to create an application in which the user can enter a text field, press a button and have a new text field appear and they can continue adding text fields in this way.
My solution was to have the top level be a scrollview and then have a relative view as a child within that(this way I can then programatically insert more editviews in my code with the OnClick() listener.
I have seen and read a couple of other posts pertaining to relative views but it seems there is still something that I am missing. I have tried
Here is the xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_create_accounts"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.nic.mybudget.CreateAccountsActivity">
<RelativeLayout
android:id="#+id/activity_create_accounts_relativeLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/activity_name"
android:inputType="textAutoComplete"
android:layout_alignParentTop="true"
android:id="#+id/activity_createAccounts_relativeLayout_activityName"/>
<Button
android:text="+"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_below="#+id/activity_createAccounts_relativeLayout_activityName"
android:id="#+id/activity_create_accounts_relativeLayout_activityName_addButton" />
<Button
android:text="Save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_below="#+id/activity_create_accounts_relativeLayout_activityName_addButton"
android:layout_centerHorizontal="true"
android:id="#+id/activity_create_accounts_relativeLayout_activityName_saveButton" />
</RelativeLayout>
And here is the Code where I try to add new editviews.
public class CreateAccountsActivity extends Activity {
static private final String TAG = "MAIN-Activity";
int numAccounts = 0;
int lastAccountID;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_accounts);
final RelativeLayout Relative = (RelativeLayout) findViewById(R.id.activity_create_accounts_relativeLayout);
final TextView oldAccount = (TextView) findViewById(R.id.activity_createAccounts_relativeLayout_activityName);
final TextView newAccount = new TextView(this);
final Button addNewAccountButton = (Button) findViewById(R.id.activity_create_accounts_relativeLayout_activityName_addButton);
addNewAccountButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG, "addNewAccountOnClick");
numAccounts = numAccounts+1;
int newAccountID = oldAccount.getId() + numAccounts;
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
newAccount.setLayoutParams(rlp);
newAccount.setHint("Hint" );
newAccount.setId(newAccountID);
Relative.addView(newAccount);
RelativeLayout.LayoutParams blp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
blp.addRule(RelativeLayout.BELOW, newAccountID-1);
addNewAccountButton.setLayoutParams(blp);
}
});
}
}
As you can see what I am trying (and failing) to do is add the new edit view at the top of the page and simply push everything else down the page. What am I getting wrong here with the relative layout?
Any help is appreciated.
First thing View with id activity_createAccounts_relativeLayout_activityName is EditText and you are casting it with TextView so that is wrong cast it to EditText.
And to your actual problem:
You are using same EditText instance with variable newAccount and adding it again in relative layout if you want to add one more EditText in relative layout you have to initialise EditText inside onclicklistener.
Just add one line newAccount= new EditText(context)in your onclicklistener code before line numAccounts = numAccounts+1;
Happy Coding !
My Android game project needs a "New Game" activity. The game has a couple of options that should be asked each time a new game is started: the board size and the game seed. I would like to do this in a form resembling the standard "Settings" activity, but with an added "Start" button at the bottom. Given that these things will be chosen every new game, they don't want to be hidden away in the app's Settings activity. So what's the best way to go about this?
Things I've investigated:
Using a custom PreferenceActivity, since the behaviour is almost the same. Since the PreferenceActivity doesn't use layout XML files I can't see a way of adding a button to it.
A Linear layout that includes a ListView and a Button. I've started implementing this, but I can't even find a way to add items to the ListView - the ListView guide in the documentation certainly isn't aimed at a beginner like me! And then the list items need to be interactive to allow options to be selected: this looks like a lot of work to duplicate what PreferenceActivity almost does on its own.
Is there an option that I'm missing? I've spent a couple of hours trying to find an answer in the documentation and in previous questions, but with no progress. If anyone can point me in the right direction I'd be grateful.
Here is some code for you. Hope it will be useful.
You should go by the second way and use LinearLayout (this is main.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="#+id/lvSimple"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
<Button // describe your start button here/>
</LinearLayout>
Layout for ListView item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="#+id/ivImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher">
</ImageView>
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<CheckBox
android:id="#+id/cbChecked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CheckBox">
</CheckBox>
<TextView
android:id="#+id/tvText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="20dp"
android:text="TextView">
</TextView>
</LinearLayout>
</LinearLayout>
Your MainActivity.java:
public class MainActivity extends Activity {
// имена атрибутов для Map
final String ATTRIBUTE_NAME_TEXT = "text";
final String ATTRIBUTE_NAME_CHECKED = "checked";
final String ATTRIBUTE_NAME_IMAGE = "image";
ListView lvSimple;
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// data array
String[] texts = { "sometext 1", "sometext 2", "sometext 3",
"sometext 4", "sometext 5" };
boolean[] checked = { true, false, false, true, false };
int img = R.drawable.ic_launcher;
// our data source
ArrayList<Map<String, Object>> data = new ArrayList<Map<String, Object>>(
texts.length);
Map<String, Object> m;
for (int i = 0; i < texts.length; i++) {
m = new HashMap<String, Object>();
m.put(ATTRIBUTE_NAME_TEXT, texts[i]);
m.put(ATTRIBUTE_NAME_CHECKED, checked[i]);
m.put(ATTRIBUTE_NAME_IMAGE, img);
data.add(m);
}
String[] from = { ATTRIBUTE_NAME_TEXT, ATTRIBUTE_NAME_CHECKED,
ATTRIBUTE_NAME_IMAGE };
// array of IDs of Views
int[] to = { R.id.tvText, R.id.cbChecked, R.id.ivImg };
// create adapter
SimpleAdapter sAdapter = new SimpleAdapter(this, data, R.layout.item,
from, to);
// create ListView and set the adapter
lvSimple = (ListView) findViewById(R.id.lvSimple);
lvSimple.setAdapter(sAdapter);
}
}
I'm trying to create a list of keys from a SharedPreferences object. Since the user can add new pairs key-value, I need to do it dynamically.
Here is the onCreate function of my activity:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = this.getLayoutInflater();
LinearLayout layout = (LinearLayout)inflater.inflate(R.layout.activity_show_saved, null);
this.add_here = (LinearLayout)layout.findViewById(R.id.saved_list);
// Loading shared preferences
SharedPreferences sp = this.getSharedPreferences("saved_sequences", MODE_PRIVATE);
Map<String, ?> kv = sp.getAll();
int i = 0;
// Iterating through shared preferences
for(Map.Entry<String, ?> entry : kv.entrySet()) {
Toast.makeText(this, entry.getKey(), Toast.LENGTH_SHORT).show();
TextView to_add = new TextView(this);
to_add.setText(entry.getKey());
to_add.setId(i++);
this.add_here.addView(to_add, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
this.setContentView(layout);
}
Where this.add_here is a class variable declared as private LinearLayout. And here is the xml file which is being inflated:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/background"
tools:context=".ShowSaved" >
<com.google.ads.AdView
android:id="#+id/adViewTop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
ads:adUnitId="*****************"
ads:adSize="SMART_BANNER"
ads:testDevices="TEST_EMULATOR"
ads:loadAdOnCreate="true" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/saved_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
</ScrollView>
</LinearLayout>
Unfortunately I get a blank screen. The problem is in adding the TextViews, since the Toast inside the while correctly shows saved keys as it's expected to do.
I've just done similar dynamic list, but my TextView is a part of a stand-alone layout.
Perhaps this will do the trick for you.
This code works for me:
final ScrollView ll = (ScrollView) getLayoutInflater().inflate(
R.layout.dropdown_list, null);
final LinearLayout container = ((LinearLayout) ll
.findViewById(R.id.dropdown_list_container));
if (myObjectsCount > 0) {
for (final MyObject ci : myObjects()) {
LinearLayout item = ((LinearLayout) getLayoutInflater()
.inflate(R.layout.list_item, null));
TextView tv = ((TextView) item
.findViewById(R.id.list_item_text));
tv.setText("your text here");
container.addView(item);
}
}
And the layout for the text view:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/buttons"
android:clickable="true"
android:gravity="center_vertical"
android:orientation="horizontal" >
<TextView
android:id="#+id/list_item_text"
style="#android:style/Widget.TextView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical" />
</LinearLayout>
As someone have already stated in the comments, that was not the right way of doing it. Here is the result achieved using a ListView. Have a look.
public class ShowSaved extends Activity implements OnItemClickListener {
// Layout
private ListView add_here;
private TextView empty_view;
// String Array
private ArrayList<String> string = new ArrayList<String>();
// SharedPreferences object and editor
private SharedPreferences sp;
// Array adapter for ListView add_here
private ArrayAdapter<String> saved;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_show_saved);
this.add_here = (ListView)findViewById(R.id.saved_list);
this.empty_view = (TextView)findViewById(R.id.empty_text);
// Loading shared preferences and editor
this.sp = this.getSharedPreferences("saved_sequences", MODE_PRIVATE);
// Creating the Adapter with all strings in an array
this.saved = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, string);
this.saved.setNotifyOnChange(true);
// Retrieving all pairs in SharedPreferences sp
Map<String, ?> kv = sp.getAll();
// Iterating through shared preferences
for(Map.Entry<String, ?> entry : kv.entrySet()) {
saved.add(entry.getKey());
}
// Setting Adapter to ListView and empty View
this.add_here.setEmptyView(empty_view);
this.add_here.setAdapter(this.saved);
// Setting Listener for ListView add_here
this.add_here.setOnItemClickListener(this);
}
Note: this code won't compile on its own since it lacks the onItemClick function required for the OnItemClickListener interface.
In my activity I do
TextView bTitle = (TextView)findViewById(R.id.TextView);
bTitle.setText(Html.fromHtml(title));
where title is a string
but i get a null pointer exception at second line ie. bTitle.setText(Html.fromHtml(title));
can anyone help???
Activity
public class NewsDetails extends ListActivity{
public static final String LOG_TAG = "Infra";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listplaceholder);
super.onStart();
Intent myIntent = getIntent();
String id = myIntent.getStringExtra("content_id");
String title = myIntent.getStringExtra("title");
//Spanned newTitle = Html.fromHtml(title);
//tv.setText(Html.fromHtml(title));
TextView bTitle = (TextView)findViewById(R.id.TextView);
Log.d(LOG_TAG, "What is the value: " + bTitle);
bTitle.setText(Html.fromHtml(title));
ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
String xml = XMLfunctions.getBodyXML(id);
String result = xml.replaceAll("<p>", "<p><div align=\"justify\">");
String nXml = result.replaceAll("</p>", "</div></p>");
TextView body = (TextView)findViewById(R.id.TextView1);
body.setText(Html.fromHtml(nXml));
//Spanned body = Html.fromHtml(nXml);
/*HashMap<String, String> map = new HashMap<String, String>();
map.put("title", tv.toString());
map.put("news", tv1.toString());
mylist.add(map);*/
/*ListAdapter adapter = new SimpleAdapter(this, mylist , R.layout.list_item, new String[] { "title", "news" }, new int[] { R.id.item_title, R.id.item_subtitle });
setListAdapter(adapter);
final ListView lv = getListView();
lv.setTextFilterEnabled(true);*/
}
Layout - listplaceholder.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="#id/android:list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawSelectorOnTop="false" />
<TextView
android:id="#id/android:empty"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="No data"
android:focusable="false"
android:clickable="true"/>
</LinearLayout>
text_view.xml
<LinearLayout android:id="#+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="#+id/TextView"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:textSize="16px"
android:textStyle="bold">
</TextView>
<TextView
android:id="#+id/TextView1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:textSize="16px"
android:textStyle="bold">
</TextView>
</LinearLayout>
You should load the correct xml for your layout
setContentView(R.layout.text_view)
TextView bTitle = (TextView)findViewById(R.id.TextView);
bTitle.setText(Html.fromHtml(title));
i found two issue in your code
1)first thing is your TextView is not in listplaceholder.xml ..
so you it will be null pointer...
2)and you need add this code before setContentView();
Intent myIntent = getIntent();
String id = myIntent.getStringExtra("content_id");
String title = myIntent.getStringExtra("title");
and let me know what u want in list and where you call setAdapter for list , where is your adapter...
Make sure, that you actually have the
<TextView android:id="#+id/TextView [...]
view in your activity's layout xml.
Update
In your listplaceholder.xml there is no such TextView!
If you use the text_view.xml layout as your item renderer, then the code that tries to access the TextView should be placed inside your ListAdapter implementation's getView method!
1) Make sure R is imported from your project (and not from android.R namespace) in your import(s) section on the top
2) After the
TextView bTitle = (TextView)findViewById(R.id.TextView);
perform a log:
Log.d("debug", "bTitle: " + (bTitle != null));
and check out from terminal (if you're using Linux, if Windows, just run the logcat)
adb logcat | grep bTitle
This should tell you if you properly got the TextView from your layout (if it is present in the layout, like #rekaszeru mentioned).
3) Make sure the title variable is not null as well
Thank you all for your help. I have replaced textview with webview as i needed a lot of html formatting in my application and now my text appears in proper format and also my appliction is running fine.
Thanks