So I'm wondering how to go about filling a ListView with empty rows. The ListView is populated via SQLite db so say for instance there is only 3 items in the list I want to fill the rest of the screen with empty rows. Here is a screenshot of what I mean. Yes I know it's from iPhone but it demonstrates what I mean:
The cheap way is to add extra "rows" in your layout xml. Any extra rows will be cut off by the screen. This can get messy: a higher-res screen might require you add many extra TextViews. Since they get cut off, I suppose you could add as many as you'd like. It would look something like this:
<LinearLayout>
<ListView></ListView>
<TextView/>
<TextView/>
<TextView/>
...
</LinearLayout>
Another option is to add extra rows to your ListView, as mentioned previously. If you are bound to an array, add extra blank rows to the array and handle it appropriately. Coincidentally, if you are using a Cursor you can use a MaxtrixCursor & MergeCursor as described in this answer
I ended up using a combination of these methods. I try my best to calculate the number of rows I want to add to my ListView, but I error on the side of caution and have a couple TextViews underneath my ListView that make it all come together.
When you create the Array the is going to be bound to the ListView you just need to add a few rows at the end of the Array with empty strings.
Using a textview below the listview seems to give the illusion of what I was going for.
#kabir's solution works. Now if you are like me (wanted to have two alternate colors in background, this is his dispached method rewritten (or let's say edited)
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
int caseLastChildBottom = -1;
int caselastChildHeight = -1;
int caseNrOfLines = -1;
//makes the colors follow the order (alternateColor1 - alternateColor2 - alternateColor1 - etc.)
int plusIndex = 1;
if (this.getChildCount() % 2 == 0)
plusIndex = 0;
// ListView's height
final int currentHeight = getMeasuredHeight();
// this will let you know the status for the ListView, fitting/not fitting content
final int scrolledHeight = computeVerticalScrollRange();
//empty listview (no item)
if (scrolledHeight == 0) {
//no childs exist so we take the top
caseLastChildBottom = 0;
//last child doesn't exist, so we set a default height (took the value in dp in the item row's height)
caselastChildHeight = convertDpToPx(DEFAULT_CHILD_ROW_S_HEIGHT);
// determine the number of lines required to fill the ListView
caseNrOfLines = currentHeight / caselastChildHeight;
}
//there is a remaining gap to fill
else {
final View lastChild = getChildAt(getChildCount() - 1);
if (lastChild == null) return;
// values used to know where to start drawing lines
caseLastChildBottom = lastChild.getBottom();
// last child's height(use this to determine an appropriate value for the row height)
caselastChildHeight = lastChild.getMeasuredHeight();
// determine the number of lines required to fill the ListView
caseNrOfLines = (currentHeight - caseLastChildBottom) / caselastChildHeight;
}
// values used to know where to start drawing lines
final int lastChildBottom = caseLastChildBottom;
// last child's height(use this to determine an appropriate value for the row height)
final int lastChildHeight = caselastChildHeight;
// determine the number of lines required to fill the ListView
final int nrOfLines = caseNrOfLines;
int i = 0;
for (i = 0; i < nrOfLines; i++) {
Rect r = new Rect(0, lastChildBottom + i * lastChildHeight, getMeasuredWidth(), lastChildBottom + (i + 1) * lastChildHeight);
canvas.drawRect(r, (i + plusIndex) % 2 == 0 ? alternateColorView1 : alternateColorView2);
}
//is there a gap at the bottom of the list
if(currentHeight - (nrOfLines *lastChildHeight) > 0){
Rect r = new Rect(0, lastChildBottom + i * lastChildHeight,getMeasuredWidth(), currentHeight);
canvas.drawRect(r, (i + plusIndex) % 2 == 0 ? alternateColorView1 : alternateColorView2);
}
return;
}
I forgot these two Paint colors (just as #kabir declared the colors):
alternateColorView1.setColor(....);
alternateColorView1.setStyle(Paint.Style.FILL);
alternateColorView2.setColor(....);
alternateColorView2.setStyle(Paint.Style.FILL);
Related
I need to add tint to a picture and then revert the picture back to its original color. I am able to add tint but don't know how to revert the picture back to it's original colors.
I want to create a method where it resets the picture back to its original color.
Attempt
public void changeBlues(double param){
Pixel[] pixelArray = this.getPixels();
Pixel pixel = null;
int value = 0;
int index = 0;
if(param <= 0.0){
System.out.println("Error! Parameter less than or equal to 0.0");
return;
}
else if(param > 5.0){
System.out.println("Error! Paramater is greater than five.");
return;
}
//loop through all the pixels
//get the current pixel
while(index < (int)(pixelArray.length)){
if(param < 1.0){
pixel = pixelArray[index];
//get the value
value = pixel.getBlue();
// decrease the value by param
value = (int)((value - (value * param)));
// set he blue value of the current pixel to the new value
pixel.setBlue(value);
// increment the index
index = index + 1;
}
pixel = pixelArray[index];
//get the value
value = pixel.getBlue();
// decrease the value by param
value = (int)((value + (value * param)));
// set he blue value of the current pixel to the new value
pixel.setBlue(value);
// increment the index
index = index + 1;
}
}
As suggested by MadProgrammer, you need to either maintain a copy of the original, or create a (bidirectional) delta for each change. The advantage of the later is, that you can revert to all stages of your editings, sort of like a history (CTRL + Z/Y in many programs under windows).
To do this, you need to create an object that stores the pixel change information and can be applied or reverted. Since you loop over all pixels, and practically almost all pixels will be affected, you could just store the entire image in the history. This depends on whether you will have operations in your program that change the image on a more limited basis, instead of making whole-picture-modifications.
#Edit:
Since you want to rotate between multiple different tinted pictures, aparrently, just genreate the three buffered pictures and rorate them.
I'm looking for a way to populate a gridview from the bottom left going across and up rather than the top left going across and down, but also still be able to use pointToPosition(x, y) to get the correct element in the array (so bottom left would be 0).
I'm not entirely sure if this is possible or not but I guess it must be, however I can't think of any way to do it without messing up the ability to find the array indices properly. Any help would be appreciated.
here is the code to get the string array used to fill the grid:
int num = 0;
//populates a standard array from the grid in the JSONObject
for (int vertical = 0; vertical < puzzleArray.size(); vertical++) //rows
{
for (int horizontal = 0; horizontal < puzzleArray.get(0).length(); horizontal++) //columns
{
//adds each letter of each row stored in puzzleArray to puzzleInputArray
puzzleInputArray[num] = puzzleArray.get(vertical).charAt(horizontal) + "";
num++;
}
}
The puzzleArray comes in as 9 strings of 9 letters which are then separated into a seperate array with the code above.
I fill the GridView with a standard ArrayAdapter:
//fill GridView with the puzzle input array from the puzzle class
ArrayAdapter<String> gridAdapter = new ArrayAdapter<String>(c, R.layout.cell_layout, todaysPuzzle.puzzleInputArray);
wordsearchGrid.setAdapter(gridAdapter);
And I need to be able to call the equivalent of this on the grid:
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
startPosition = wordsearchGrid.pointToPosition((int)downX, (int)downY);
letterDown = (String) wordsearchGrid.getItemAtPosition(startPosition);
Thanks.
to solve your problem, you simply have to use more advances techniques to create your adapter.
Writing an adapter in one line of code is great, but to get a more customized experience of adapting your array to a gridView, you will have to write a BaseAdapter yourself.
From there, it will be quite simple, you can for example have two arrays as its member variables, one to store the "real" indexes, and one to the "displaying" indexes.
Hope I helped you :) !
I've a weird issue,
I've a table with 2 columns and 3 rows
each cell text can be edited at run time, when I edit the cell in the 3rd row second column I get the upper cell modified too with the same text
this only occurs on redhat6 . works fine with rhe5 and rhe4
editor of type TextCellEditor;
TableItem item = table.getItem(textEditor.getControl().getLocation());
getItem method implementation in Table.class is :
public TableItem getItem (Point point) {
checkWidget();
if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
int /*long*/ [] path = new int /*long*/ [1];
OS.gtk_widget_realize (handle);
if (!OS.gtk_tree_view_get_path_at_pos (handle, point.x, point.y, path,null, null, null)) return null;
if (path [0] == 0) return null;
int /*long*/ indices = OS.gtk_tree_path_get_indices (path [0]);
TableItem item = null;
if (indices != 0) {
int [] index = new int [1];
OS.memmove (index, indices, 4);
item = _getItem (index [0]);
}
OS.gtk_tree_path_free (path [0]);
return item;
}
I thought it might be my GTK library . I have GTK2 lib installed.
I think this error is triggered because the Text inside the TextEditorField field has some margins or minimum size that does not fit in the cell, or the row height is calculated incorrectly.
However, I suggest that you do not try to find the table item that the text editor is pointing at by using the getItem(Point), as there are probably other kinds of issues too, and this kind of behaviour cannot generally be guaranteed. I'd say that should be chiefly used to find "the one item that is being pointed to at by mouse." as in this question here. Actually you could be count yourself being lucky that you actually find out this bug.
The quick-and-dirty solution would be to calculate the center of the Text.getBounds() and use that to find the item, that is:
Rectangle bounds = textEditor.getControl().getBounds();
Point location = new Point(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
table.getItem(location);
But the better alternative, if you're running SWT >= 3.3, to use the TableViewerColumn.setEditingSupport(EditingSupport) to set the EditingSupport for each column, because with EditingSupport you can make the editor knowledgeable of which item it is editing within the table.
This question is related to one I posted earlier. Views removed using removeView() are there when I next open the Activity (Android)
Background: When a user logs into my app they are taken from the login activity to the mainpage activity. The mainpage has a TableLayout that contains dynamically generated buttons. However if the user logs out and back in again, all of these buttons are repeated so I am trying to find out how best to remove these buttons after they are generated. In my previous post it was suggested I remove the buttons at the very start of the main page activity, before the new ones are drawn, so this is what I am trying to implement.
However when I call getChildCount() on this layout it does not always return the correct answer.
So far, here is the code that is run at the start of the main page activity:
TableLayout tableLayout = (TableLayout)findViewById(R.id.MainPageTableTitle);
//removeSectionButtons(tableLayout); this is where i am trying to remove the buttons
System.out.println("there are oncreate " + tableLayout.getChildCount());
drawButtons(tableLayout);
System.out.println("there are ondraw " + tableLayout.getChildCount());
The first print line returns 0 and the second print line always returns the correct answer (number of buttons drawn including all of the repeated ones). But I am not sure why getChildCount() returns the wrong answer the first time. If anyone can explain I would be incredibly grateful
My drawButtons() method is as follows (it draws two buttons per row):
public void drawButtons(TableLayout tableLayout){
//get the number of buttons
int noOfButtons = mySectionTableHandler.getSectionDetails().size();
//calculate the number of rows needed (there are 2 columns)
//set flag to say if buttons are odd as it affects how many are drawn
int noOfRows;
boolean evenNoOfButtons;
if(noOfButtons % 2 == 0){
//even no of buttons
noOfRows = noOfButtons/2;
evenNoOfButtons = true;
} else {
//odd no of buttons
noOfRows = (noOfButtons+1)/2;
evenNoOfButtons = false;
}
//counter to give each button a unique id
int counter = 1;
for(int i = 0; i<noOfRows;i++){
TableRow newRow = new TableRow(this);
Button a = new Button(MainPageActivity.this);
a.setId(counter);
sectionButtons.put(counter, a);
counter++;
newRow.addView(a);
//if there are even buttons OR if there are an odd no
//of buttons but this isn't the last row then add
//second button to row
if(evenNoOfButtons || (!evenNoOfButtons && (noOfRows-1!=i))){
Button b = new Button(MainPageActivity.this);
b.setId(counter);
sectionButtons.put(counter, b);
counter++;
newRow.addView(b);
}
tableLayout.addView(newRow);
}
}
This was my bad, turns out I was re-adding data to the sqlite database each time the user logged in without wiping previous details.
So my code was generating a button for every field in the database as it should have been.
I figured out how to drag to highlight multiple cells in a GridLayout-designed grid (which wasn't too hard) and how to drag a cell from one such grid to another (which involved brute force and math, but it turned out not to be all that hard, either).
But the code looks and feels hacked.
How should I have done it?
Here are code fragments that typify what I did to drag content (one char):
For each cell in txtUser[] grid add mouse listener to identify the cell about to be dragged and also access its content:
txtUser[i].addMouseListener(new java.awt.event.MouseListener()
{
public void mousePressed(MouseEvent e) {
currentUserCell.index = interp(e.getXOnScreen(), ulcUser.x, txtUser[0].getWidth());
if(txtUser[currentUserCell.index].getText().length() > 0)
currentUserCell.content = txtUser[currentUserCell.index].getText().charAt(0);
}
Here's interp(), which converts from absolute screen pixel (x) to (returned) grid element number, given the upper-left corner of the text field array and the width of one element:
static int interp(int x, int ulc, int w){
return (x - ulc)/w;
}
If the user moves the frame, interp() above doesn't work, requiring need to reorient():
void reorient(){
ulcGrid = new Point(cells[ 0][ 0].getLocationOnScreen().x, cells[ 0][ 0].getLocationOnScreen().y);
ulcUser = new Point(txtUser[ 0] .getLocationOnScreen().x, txtUser[ 0] .getLocationOnScreen().y);
}
(I tried to use relative pixel locations, but couldn't make it work. I may revisit this.)
In order to drop the dragged content, the destination had better be inbounds():
boolean inbounds(int r, int c){
return ! (r >= N || c >= N || r < 0 || c < 0);
}
If inbounds, the letter is dropped, as long as destination is empty:
public void mouseReleased(MouseEvent e) {
int x, y;
if(! dragging)
return;
dragging = false;
x = e.getLocationOnScreen().x;
y = e.getLocationOnScreen().y;
int c = Utilities.interp(x, ulcGrid.x);
int r = Utilities.interp(y, ulcGrid.y);
if(! inbounds(r, c))
return;
if(cells[r][c].getText().length() > 0)
return;
cells[r][c].setText("" + currentUserCell.content);
The previous method required a MouseMotionAdapter for each cell of the source array.
And it just seems so hacked. One reason I say this is that I rely on several global variables, such as ulcGrid and ulcUser and currentUserCell and dragging:
private void txtUserMouseDragged(MouseEvent evt)
{
dragging = true;
}
I had a nice learning experience, but I'd rather have more-professional-looking code, most notably with fewer global variables. (I realize that a good start would be to not rely on absolute pixel addresses.)
So I'm asking where to find a better way, specifically how to identify the drag source and destination cells of a one- or two-dimensional array of text fields.
=================
--EDIT--
My program works. My question is about whether there is a library that would make it easier and more reliable than what I've written to drag from the one-dimenional array at the bottom of the screen below onto the large grid.
But now that I've read the comments, maybe this is just another bad question that should be deleted.