Creating numerous LIstViews or TableLayouts programatically - java

I have read various posts on programmatically creating a TableLayout/ListView and I'm still unsure of the best route to take.
In my mind I have one class called RunTests.java. One test schedule can contain numerous test types, and for each test type a table of results is required. So let's say there are four tests, named A, B, C and D.
After test A has completed I'd ideally like to call another class (ProcessTable.java) and pass it an array of test results, and array of test column headings and an array of test row headings. The class would then return a table, complete with results and headings, and inflate it so it becomes visible within an XML LinearLayout, and then move on to test B.
The process would then repeat and the next table would appear below the first one, and so on.
Any advice or examples would be great.
Thanks
Attempt at suggested answer:
I'm getting an error on listView, I'm not sure where I define this. The XML I've added to be existing layout is below:
private void createTable() {
String[] columns = {"row_header", "column_name1", "column_name2"};
String[] results = {"","2000","98"};
int[] to = { R.id.row_header, R.id.txt1 ,R.id.txt2};
String[] rowHeadings = {"","Bandwidth","QoS"};
List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
for(int i = 0; i < rowHeadings.length; i++){
HashMap<String, String> map = new HashMap<String, String>();
map.put(columns[0], rowHeadings[i].toString());
map.put(columns[1], results[1]);
map.put(columns[2], results[2]);
data .add(map);
}
SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), data, R.layout.runtests, columns, to);
listView.setAdapter(adapter);
}
XML:
<LinearLayout android:id="#+id/resultsLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:background="#drawable/curvedbg"
android:layout_marginTop="10dp"
android:padding="5dp"
android:weightSum="99">
<TextView android:id="#+id/row_header" android:layout_weight="33" />
<TextView android:id="#+id/txt1" android:layout_weight="33"/>
<TextView android:id="#+id/txt2" android:layout_weight="33"/>
</LinearLayout>

My gut tells me you should be using a ListView. This will cater well to generating Views on the fly for varying data types. Also, if you have a rather large list of results that can't fit onto the screen, The ListView will auto handle scrolling and will only maintain in memory the data that displays to the screen.
On the other hand you'll need to wrap the TableLayout with a ScrollView and it will maintain all Views generated in memory...whether or not they are shown on the screen. You'll also need to setup a lot of boiler plate code just to get Views generated and attached to the main XML. In short, TableLayout would be great for static data.
Going with the ListView approach, it sounds like you should be using a SimpleAdapter. Not to terribly common as they are only useful for certain situations. Honestly the name should be ListMapAdapter as that's how it stores and expects data to be passed to it...via a List of Maps and it can be more difficult to use then an ArrayAdapter because it has one of the most confusing constructors ever. Basically the SimpleAdapter is great for rendering table like layouts, where you have columns of data.
Here's a basic example to give you an idea of how to use. This works for displaying Strings of data directly to a TextView.
//Columns is used to assign a column to a TextView. So columns[1] will place all data
//found in column 1 into to[1]...which is the TextView R.id.txt1. Columns is also used
//to map which data item belongs to a particular column
String[] columns = {"row_header", "column_name1", "column_name2", "column_name3"}
int[] to = { R.id.row_header, R.id.txt1 ,R.id.txt2, R.id.txt3};
//This is where you will assemble the test data. Probably the most difficult part
//as you must convert your test results into a List of Maps. Each index in the
//List represents a row of data. The Map represents all the columns of data for
//that row.
List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
for(int i = 0; i < rowHeadings.size(); i++){
HashMap<String, String> map = new HashMap<String, String>();
map.put(columns[0], rowHeadings.get(i));
map.put(columns[1], Your_data_for_column1);
map.put(columns[2], Your_data_for_column2);
map.put(columns[3], Your_data_for_column3);
data .add(map);
}
SimpleAdapter adapter = new SimpleAdapter(getContext(), data, R.layout.list_layout, columns, to);
listView.setAdapter(adapter);
Higher Overview Example of list_layout.xml
<LinearLayout>
<TextView android:id="#+id/row_header"/>
<TextView android:id="#+id/txt1"/>
<TextView android:id="#+id/txt2"/>
<TextView android:id="#+id/txt3"/>
</LinearLayout>
Note whether or not the SimpleAdapter works for your data is more detail dependent. Using an ArrayAdapter, CursorAdapter, etc is just as viable. It all boils down to how your data is organized. Also, if you need to display your data in a more complex way then just Strings...you may need to override the adapters' getView()...and if thats the case, definitely be sure to use the adapter whose data organization best matches yours.

Related

FXML ListView, I can't add my ObservableArrayList<Pane> to it

I'm writing a messenger in Java and FXML and I want to show all the current chats of the user on a ListView(chatBar). My chats are in an ObservableArrayList but I still can't add the values to the ListView.
public void fillChatBar() {
ArrayList<Chat> chats = db.getAllInvolvedChats(user.getUserID());
ObservableList<Pane> chatHolder = FXCollections.observableArrayList();
chats.forEach(chat -> {
Pane chatPane = new Pane();
Label chatName = new Label();
chatName.setText(chat.getOpponent(user.getUserID()).getUsername());
chatPane.getChildren().add(chatName);
chatPane.getChildren().add(new ImageView(chat.getOpponent(user.getUserID()).getProfileImage()));
chatHolder.add(chatPane);
});
chatBar.setItems(chatHolder);
}
I get no error messages or exceptions. It just won't show.
the problem is that you misunderstood the usage of ListView ;)
The items that are stored in a ListView are no cell-views but models. Internally the ListView creates cells that represents the model items and shows them on screen. You can try this by simply creating a ListView<String> and add a list of Strings to the items. You will see labels that shows the String values omg the screen. For such basic datatypes like String your ListView automatically creates cell-views to hat makes sense. For more complexe model types (like a list of custom models) you need to write your own cell-view factory (or overwrite toString() in your model class). See this tutorial as a first example to work with Strings. A more complexe example can be found here.

JavaFX: Create custom data attributes for nodes

I am currently in need of custom attributes which I can fetch anytime. Is there any way to create custom data attributes for nodes and then get those values in javafx?
Lets assume I have the the follwing Button.
<Button text="Im a button" fooBar="I hold some value" />
Similar to: https://developer.mozilla.org/de/docs/Web/Guide/HTML/Using_data_attributes
Now in HTML I could simply do the following:
<div id="example" data-foobar="I hold some value"></div>
Then I could easily get the data like this:
document.getElementById("example").dataset.foobar;
Edit: I need more than 1 data property for a node because a node can hold various information.
The data can be stored in the properties ObservableMap of a Node
Node node = ...
node.getProperties().put("foo", "bar");
...
Object foo = node.getProperties().get("foo");
Note however that some layout properties use this map too, so no property names similar to javafx properties / "static" properties should be used as key. To be sure you could create a custom key class that does not return true if an object of another type is passed as parameter to equals.
To solve your problem you should to use userData it can be any object that you need.
node.setUserData("Hello world");
node2.setUserData(123);
etc.
If you need to set multiple values you can save your values in an array, list, json etc.
ArrayList<String> vals = new ArrayList();
vals.add("Hello");
vals.add("World");
node3.setUserData(vals);
//some code
ArrayList<String> result = (ArrayList) node3.getUserData();

custom rows in ListView

i have the following problem, I am writing an app that repeats the http://www.rottentomatoes.com/mobile/ website, if you look on the site there are deviders the "Opening this Week", "Top Box Office" and "Also in Theaters" so my question is, how do i add this custom rows to the ListView that holds all the movies
here is what i have so far, please pitch me some ideas so it will look exactly like on the site
The easiest way to achieve this would be to include the dividers in the layout of item views. Then make them VISIBLE only when the view maps to the first item of a new category, otherwise leave them as GONE.
Example (in semi-pseudocode):
First, make your item layout like this:
<LinearLayout orientation=vertical>
<TextView id=divider>
<your original item layout>
</LinearLayhout>
Then, in the adapter's getView():
Film item = getItem(position);
boolean needsDivider = (position == 0 || getItem(position - 1).filmCategory != film.filmCategory);
if (needsDivider)
{
dividerView.setVisibility(View.VISIBLE);
dividerView.setText(getFilmCategoryName(film.filmCategory));
}
else
dividerView.setVisibility(View.GONE);
A more fancy solution would be to use a library like StickyListHeaders. It doesn't work as your mobile site example, but it's probably even better (e.g. the headers don't scroll up out of the screen).

Add items to ListView Android

I have an app that gets all the .mp3 files off of a storage device and I want to add them to a ListView when the app is created. I am lost on adding items to the list. I have googled it and I cannot a good defintion of what the dev is going and why they are adding what they are adding. I would like someone to tell me how to add items to a ListView and also, if they can, explain what they are doing as they are doing it so I understand and learn from it. I am a new Android Dev and looking to learn as much as I can and not just fix my code.
So, my current code is...
XML
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/ListView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
and I do not know what to do on my main activity. I so far have...
File storageDir = new File("/mnt/extSdCard/");
ArrayList<String> listItems=new ArrayList<String>();
ArrayAdapter<String> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
walkdir(storageDir);
}
public void walkdir(File directory) {
TextView songList=(TextView)findViewById(R.id.textView);
String fileType = ".mp3";
File[] listFile = directory.listFiles();
if (listFile != null) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].isDirectory()) {
walkdir(listFile[i]);
} else {
if (listFile[i].getName().endsWith(fileType)){
//I need to add the items to the ListView right here.
//listFile[i].toString() is the code to get the text, aka what i want to add
}
}
}
} }
To start with, in your activity, you should extend ListActivity instead of Activity. This will give you access to a method called setListAdapter (there are other ways, but this is probably easiest).
The setListAdapter method takes an adapter as its parameter, so we now need to create an adapter that we can pass it.
To do so, write the following:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
listFile);
I'll break that down a little bit:
The first part (this) is where we pass it the context.
The second part is the layout file that represents each individual list item. To save us having to create one, we are using one that android has built in.
Finally, we need to pass it the words you want it to display (in your case, a string array, although it could also be an ArrayList of strings.
Once you've done that, we just need to pass the adapter to our setListAdapter method, like so
setListAdapter(adapter);
But before you run your code, we need to add one little line to the XML file. When you extend ListActivity, Android will be looking for a list whose id is android.R.id.list, so we need to set the id like so:
<ListView
android:id="#android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
initialize your list adapter after fetching mp3 file names.
adapter = new ArrayAdapter(yourContext,android.R.layout.simple_list_item_1,yourFileNameList);
Looking at your code you are trying to convert the mp3 file to string and showing in listview. You can just show the filename.
You need to set adapter for the custom listview you have built.
Go to youtube and search for videos by Slidenerd. He has all the basic tutorials for android. The listview tutorials start from #77.

Spinner not a view that can be bounds(sp) by this SimpleCursorAdapter

I'm trying to adapt my query to my spinner object with some trouble, I get the error listed as the title. Here is the code portion where it crashes:
Spinner classDropDown = (Spinner) this.findViewById(R.id.classDropDown);
int[] to = new int[] { R.id.classDropDown };
String[] classFields = new String[] { "className" };
SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this, R.layout.main, cursor, classFields, to);
cursorAdapter.setDropDownViewResource(R.id.classDropDown);
classDropDown.setAdapter(cursorAdapter);
I had a problem where the cursor wasn't being filled but fixed that now. Can someone give me help on debugging this issue?
Edit: I think my problem is the "to" field. What should this be?
Edit 2: Also, here is the XML for the spinner object:
<Spinner
android:id="#+id/classDropDown"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Edit 3: I've fixed the above to reflect fixing the code. This fixes this particular problem. I'm not getting the error, but I also have nothing displayed in the spinner.
To is a list of resource ids that you want to put your data into, such as R.id.textview1, and they meed to be contained in the layout you specify in the adapter. The number of elements should also match the number of elements in your from array ( you called it classfields).
So, you have two pieces of data and only specified one target resource id. Either remove one of the fields in your classfields array or add a widget to your layout and call.it in your to array and it should work.

Categories