Good day to all.
Is there some way to order the TableLayout content by a specific column?
I need to order the content according to user selection from a spinner.
Example if the user chooses to order the table by "name" the column name is arranged in ascending order.
The rows contain TextViews in which said content is saved, and the content is populated via a database.
Is there an easier way to order the content other than having to re-open a connection to the database?
Thanks.
The only way i can think of is to create a java object for your table row entries, putting all your objects into a list and comparing them using something like this:
Collections.sort(nodeList, new Comparator<DataNode>(){
public int compare(DataNode o1, DataNode o2){
if(o1.degree == o2.degree)
return 0;
return o1.degree < o2.degree ? -1 : 1;
}
});
It would be easier to re-open a connection to the database. You have to redraw your TableLayout in all cases.
Related
I want to iterate through a list of data and populate a table with preset rows.
The naming convention is r#t1 where r# is the row number and t1 is the text field number - r# is the only thing that changes, incrementing through the rows of the table.
I can not seem to get this to work, I know you can do it through findViewById<EditText>(resources.getIdentifier("r${i+1}t1")), but I am wondering if it can be done with binding as well as it is much cleaner.
Here is some code of what I have tried:
for(i in 0..data.size-1){
binding."r${i+1}t1".text = data[i].name //how I want it to work
}
binding.r1t1.text = data[0].name // how I currently have to go about it.
binding.r2t1.text = data[1].name
...
Any suggestions would be awesome.
I have in my app a database with two tables : country and rights. Long story short, the db tells me whether a right (there is 10 rights in total) is legal or not in a specific country.
Now, I want the user to be able to search in my db by criterias. I have a layout with checkbox. If the user check a box, it mean he want to see every country in where the right is legal. For exemple, if he check the box "criteria1" and "criteria6", the user want the list of every country where criteria1 and criteria6 are legal, but we don't care wether the other rights are legal or not.
I asigned values to the checkboxs (1 if legal, 0 if illegal, just like in my db) and passes all of them to the activity who display the result of the search.
My problem is, I can't figure out how to search in my database. I need to only get the country where where the selected criters are equal to 1, but I don't know how to formulate my sql request (since I never know which criterias are going to be checked or not). My request need to only be about the criterias who has the value 1.
I had the idea of sending all my values to a function (witch returns a cursor) where I excecute a select statement if the value is equal to one, but I don't know how I could join all the result of my selects in a cursor. I also thought about using "CASE WHEN..." but it doesn't seem to work.
Does anyone have a clue on how I could deal with my search ?
If you need precisions on my problem, please ask.
This guy here (https://www.youtube.com/watch?v=NGRV2qY9ZiU&list=PL200JxfhYIgCrrpH4rCz-uNfBTb5sng1e) has the right idea.
The clip may be a bit slow but it does exactly what you want.
He creates a custom string based on if checkbox is checked and removes it from the string if unchecked.
To get what you want, you need to do a couple of things.
First, create a table with countries as rows, and rights as columns. Add 1 for right is present in country and 0 if not. Get this into an sqlite database (eg import via csv in DB browser for SQLite, free software; don't forget to create the android_metadata table in the sqlite database - search online for this). Import the database in the app (there is plenty of documentation for this online).
Second, change the text inputed in the if/else checkbox part of the script (he writes fruit names, you write for ex. "right1 = 1", or the exact query the checkbox should do on the column right1).
You also need to pay attention to the selection.add and selection.remove (know that selection is an array list which will store all your criteria for search by column).
Third, you need to change the content of his finalSelection (View view).
Delete all he has written and just create two strings:
String final1 = android.text.TextUtils.join(" or ", selection);
String final2 = "select country from table where " + final1;
The string final2 is your key for a cursor with a rawQuery. Just create a cursor in the database and pass the key to it. This can be done easily.
PS the method android.text.TextUtils.join() is amazing :)
You can place the operator of choice there.
If you need more than one operator (and, or etc), you can create different ArrayLists which you fill in the if/else checkbox is filled and join later in the finalSelection.
Oh, btw, if you have too many checkboxes, you will get a warning in the XML file (layout has more than 80 views is bad for performance).
In order to get around that, you need to get to know grid views a bit better. After reading a few tutorials on the basic use of GridViews, a good start for checkboxes inside them is here.
It may seem like a lot, but you need to learn to use holders to get information out of the getView of the modified BaseAdapter.
If you want to understand it better, follow the arrPath.
It is a String[] filled with all the paths of images found inside the cursor (string values from the dataColumnIndex, which contains paths of images).
Within the onClick() listener of the Button, from the arrPath he extracts only the rows of the cursor that were selected by checkbox click (thumbnailsselection[i] is a boolean - with a value TRUE/FALSE for each row in the cursor).
The selected paths are placed in the selectImages String, separated by OR.
I have a database consisting of columns:
bookId, pageNbr, text
where bookId and pageNbr are indexed.
Now, in using it as a data model for my list view, should I initialize a cursor using:
SELECT bookId, pageNbr, text
FROM table
WHERE bookId BETWEEN 1 AND 5
AND pageNbr BETWEEN 100 AND 500
Or should I get each item for each row, each time getView is called using this:
SELECT bookId, pageNbr, text
FROM table
WHERE bookId = VAR_BOOK_ID
AND pageNbr = VAR_PAGE_NBR
Is there any performance difference? (perhaps overhead if any for each query?)
Use whatever query is easier to handle (i.e., the first one). This results in the most efficient development performance.
Think about optimizing only when you measure an actual problem.
As for the queries: only one BETWEEN can be optimized with an index, so you need to index only the column that has greater selectivity.
And doing two lookups with = works best if there is a two-column index.
I have a table in which 5 rows are there. But I have to feed the value of row in the database in which values are filled. It can be 2nd, 3rd or all. So how would I find out and validate the same. The rows are not generating dynamically. The rows are already in layout with some ids. I know it's weird but requirement is this only. Please suggest me how can I do this.
For that you have some alternative,
I think you should insert default record into the field so that will be easy instead of validating, if you think that is good.
When get the result from the DB just put the single condition
String name = Db.get_name().toString();
if(name!=null)
{
Row_TextView.setText(name);
}
else
{
Row_TextView.setText("-"); // or what ever you want to set
}
- Here is database example
Try it i hope it works for you
What you need is a Cursor to read data from the db
Then loop through the fetched data (if 'getCount()>0' then while(!cursor.isAfterLast))
For each row check if the data is present in specific columns in your db and if not then do insert it in the db
So imagine this is a quick mockup of my database:
The items from the database are presented to the user per list, each list being displayed on a new fragment, which are displayed on a viewpager. So let's say in this hypotetical case, there would be two fragments on the viewpager, first fragment would display first_list and second fragment would display second_list. Here's the code for that query:
public static Cursor getListItems (final Context context, String listName) {
if (mDatabase == null || !mDatabase.isOpen())
open(context); //This gets the writable db.
String where = LIST_NAME + " = '" + listName + "'";
return mDatabase.query(TABLE_LIST_ITEMS, PROJECTION_LIST_ITEMS,
where, null, null, null, SORT_ORDER);
}
Where SORT_ORDER is order_in_list, this works well, to begin with.
Now, the listviews are re-arrangeable using a public library, which attempts to allow the user to control the order of the items in each list. Here's where I am having issues, there is no add(int index, Object object) for the cursor, or some other easy way to manage the sorting. I first thought I could simply call mDatabase.update() to change the value for order_in_list but that works, but the results are not as intended. For example, user drags item two to position zero, remeber: zero-index values, we would now have two items with order_in_list as zero. And although I can call mDatabase.update() on item one to update his position to one, imagine how much work that'd be to handle several items on a well-formed database.
Does anyone have any good suggestions on how I could work this out? I thought I had been clever by adding the extra col for sorting purposes :(
INB4:
Yes, I Know arrays handle this well. But the database doesn't only store 4 cols, it has many more fields. Populating arrays each time from the database would be a waste of time and effort. And I would, anyways, have to write back to the database when the app is closed.
EDIT So I changed the listview to only display one String of text, and further columns upon actual clicking on the item (and therefore displaying a new fragment with the specified list item data). This allowed me to simply keep an ArrayAdapter which easily handles the drag and drop. During onStop, I update the reference only if there was a change that required to be saved:
#Override
public void onStop() {
if (updateDbOnExit) {
//Update rows on database.
for (int i = 0; i < items.size(); i++) {
//Set the order in list be the actual order on the array.
Constants.LogMessage("Updating db content");
DbManager.moveListItemTo(getActivity(), items.get(i), i);
}
updateDbOnExit = false;
}
super.onStop();
}
Where MoveListItemTo updates the value for order_in_list:
public static void moveTaskItemTo (final Context context, String item, int to) {
if (mDatabase == null || !mDatabase.isOpen())
open(context);
String where = COL_CONTENT + " = '" + item+ "'";
ContentValues mContentValues = new ContentValues();
mContentValues.put(ORDER_IN_LIST, to);
int rows = mDatabase.update(TABLE_LIST_ITEMS, mContentValues, where, null);
Constants.LogMessage(rows + " row updated. Item moved to position: " + to);
close();
}
That will work for now. However, I am still interested on knowing if there is an alternate way, especially when for example, the adapter is using data from more than one column on the database, and is therefore required to use a CusorAdapter and not a regular ArrayAdapter, which in turn requires the Database itself to update upon each Drag and Drop to reflect the change on the UI via cursorAdapter.swapCursor(). As stated, updating ALL of the items on a database upon each drag (which realistically doesn´t happen that often btw), is expensive, updating only Two rows, would be a saner choice.
I just meant I wanted a more effective way to update the fields in the db, rather than manually updating each and every single row
Make the user-specified-order column a decimal, not an integer. Then you need to update only the moved row(s).
Allow negative numbers.
0.00 cat
1.00 aardvark
2.00 wolf
3.00 dog
If "dog" is dragged above "wolf" then "dog" becomes 1.50 and no need to change other rows. If "aardvark" is dragged above "cat" (special case -- prepending to list rather than inserting between rows) then subtract 1 from the topmost value, and "aardvark" becomes -1.00.
This will require you to know the values of the adjacent rows, but you won't have to update them. Only the moved row's value must change.
I would suggest that you have an additional column, user_specified_order which would represent the user's reordering of the rows in the UI via drag-drop.
You must update each row when its user_specified_order value is invalidated by the drag-drop repositioning. When to persist that value is up to you -- either at the "end" of the user's manipulations, however that be defined (e.g. click on Save button) or after each drag/drop if there is no clearcut UI indicator of "end of manipulation".
EDIT: ContenProvider in Android:
Android - Can you update a Cursor for SQLite results?
Android SQLite transactions:
Android Database Transaction