I have several divs that are shown and hidden. How can I detect on a given element is it is currently visible on the page?
The element's style won't help, since it is a parent div in the DOM that is being hidden.
Its offset height and width will both be 0.
UIObject component = ...
boolean isHidden = (component.getOffsetHeight() == 0 && component.getOffsetWidth() == 0);
I have run into this issue before as well and I found the following to be the best solution:
Given an Element called "element":
boolean visible = UIObject.isVisible(element) && (element.getAbsoluteLeft() > 0) && (element.getAbsoluteTop() > 0);
The static "isVisible" method on UIObject will check for display none and that sort of thing, while the checks on the AbsoluteLeft and AbsoluteTop are there to handle detachment. The reason that I found the latter checks to be necessary was because if an element is detached from the DOM (and is hence not visible on the page) then GWT will still tell you that its visibility is true unless its visibility was explicitly set to false.
NB: You could replace the AbsoluteTop and AbsoluteLeft checks with the offset width and height checks as suggested by Simon, but you should include the isVisible check as well in my opinion.
You can have something like that:
public boolean isVisible(Widget w) {
while (w.getElement().hasParentElement()) {
if (w.isVisible()) {
return true;
}
w = w.getParent();
}
return w.isVisible();
}
If it's an Element, not a UIObject, the following worked for me:
!"hidden".equals(element.getStyle().getVisibility())
&& !"none".equals(element.getStyle().getDisplay())
I was walking down the tree, so knew the parent elements were visible; if your case is different, you'll probably need to do the same check on all parent elements.
Related
1) I'm practicing stuff with graphs in order to add that feture to my app, I want the upper labels ( the xAxis base ) to be shown only where entries occur.
I haven't found a suitable solution online yet, and currently it appears on every xAxis from first entry to last entry as in the picture below:
I want it to be without the one sI deleted, as shown in the picture below:
2) and the second question I'm struggling with it is that I want to be able to draw for example in (x=5, y=7) and after it to draw at (x=1, y =3), but it wont let me add an entry with a smaller x that any other entry that already in the graph.
You have to extend from ValueFormatter class.
for more detail take a look at link
You can pick your desired logic to make the label disappear with returning "".
for example:
public String getFormattedValue(float value) {
if ((int)value <= 0) //your logic to evaluate correctness
return ""; // make lable go away
//...
}
UPDATE 2 (in Kotlin):
There is another overload for getFormattedValue which have a AxisBase parameter and you can use mEntryCount or mEntries.
override fun getFormattedValue(value: Float, axis: AxisBase?): String {
if (axis?.mEntryCount!! <= 0)
return ""
}
I've just started learning JavaFX for building desktop applications and I currently don't have any personal training yet. Right now regarding the question, I'm trying to make a custom layout that depends its size to the overall size of its children. My problem is about getting the size of each child during height and width computation. Here, I'm using the getLayoutBounds() method to retrieve the children's size, but it always return 0 in my case:
#Override
protected double computePrefWidth(double height) {
for (int i = 0; i < getChildren().size(); i++) {
Node node = getChildren().get(i);
System.out.println(node.getLayoutBounds().getWidth()); // returns 0
}
}
So I guess it is about the layout pass (say, the child is not laid-out yet). But anyways, if that is the case here or not, how can I get the exact size of the node including the insets, padding, etc.? Thanks for all answers.
UPDATE
I end up using the prefWidth() and prefHeight() method which is the correct answer. It's my mistake for using the getWidth() and getHeight() method as I thought the prefWidth() method does not include paddings/insets. On the other hand, getWidth() actually rely on the layout pass, means that, it returns 0 because the nodes (children) are not laid-out yet in the stage, which is what #ᴇʟᴇvᴀтᴇ's answered below is correct.
So for the sake of others whoever come across this, you may want to read this one, and lastly, make sure all CSS stylesheets are properly applied if you are not getting expected result with the pref, min, max methods (see answers by #fabian and #SilasGyeme below).
If you implement a custom Region (or indirect subclass), it's your classes' job to determine the size of the children.
computePrefWidth ect. need to consider the size bounds of the children and determine it's own preferred size based on those values. For these kinds of calculation you should use the minWidth, minHeight, prefWidth, prefHeight, maxWidth and maxHeight methods of Node.
Example
#Override
protected double computePrefWidth(double height) {
double size = 0;
for (Node child : getManagedChildren()) {
double pW = child.prefWidth(height);
if (pW > size) {
size = pW;
}
}
// TODO: consider insets ect...
return size;
}
The above way of determining the pref size would be suitable e.g. for something like a VBox.
getWidth() returns 0 until you show the stage and layout the nodes. After that, they will have a non-zero width.
Use runLater() to run actions post layout.
Platform.runLater(() -> {
// TODO: Calculations based on laid out sizes
});
Set the setPrefWidth of the children ,then access them using getPrefWidth
Looking for a GWT DataGrid component which implements infinite scroll, BUT also makes sure to discard the results no longer visible on the screen : such as the previously loaded results that are not shown anymore.
This is to avoid a memory hog.
I've been trying to find this on Google, but no luck so far.
Please note : I could take a JS library and adapt it to what I need, but I don't think it would work good with GWT's DataGrid component.
Edit: I am interested specifically in an infinite scroll which ALSO discards/releases the topmost results that are not visible (and loads them up as appropriate).
Any ideas ?
As a matter of fact the showcase example has an infinite scrolling CellList. (you can find the code there).
Although this was done with a CellList the same principles should also apply to a DataGrid.
Check out the ShowMorePagerPanel.java file.
Update:
The onScroll function of ShowMorePagerPanel.java will add the new records at the bottom. However you can easily change the behavior:
Something along the lines (not tested tough):
HasRows display = getDisplay();
if (display == null) {
return;
}
boolean loadData = false;
// If scrolling up, change newStart
int oldScrollPos = lastScrollPos;
lastScrollPos = scrollable.getVerticalScrollPosition();
// get the current visible Range
Range currentRange = display.getVisibleRange();
if (oldScrollPos >= lastScrollPos) {
int newStart = Math.max(
currentRange.getStart() - incrementSize,0);
loadData = true;
}
int maxScrollTop = scrollable.getWidget().getOffsetHeight()
- scrollable.getOffsetHeight();
if (lastScrollPos >= maxScrollTop) {
// We are near the end, so increase the page size.
int newPageSize = Math.min(
display.getVisibleRange().getLength() + incrementSize,
display.getRowCount());
loadData = true;
}
if (loadData) {
display.setVisibleRange(newStart, newPageSize);
}
In my application, I have 2 LinearLayout's right above each other. Via a menu option, I want to be able to make the bottom one disappear, and have the top one drop down over the disappeared LinearLayout.
The problem is, I have no idea on how to do this in Java.
It doesn't have to be animated, I want to hide the Layout on return of another activity (the menu), in OnActivityResult. The menu activity sets a boolean on which I check in OnActivityResult, and according to it's value I determine if I need to hide or show the bottom Layout:
// Only change value if it is different from what it was.
if(mUseVolumeButtonAsPTT != resultData.getBoolean("UseVolumeButtonAsPTT")){
mUseVolumeButtonAsPTT = resultData.getBoolean("UseVolumeButtonAsPTT");
if(!mUseVolumeButtonAsPTT){
// Hide lower LinearLayout.
} else {
// Show lower LinearLayout.
}
}
Can anybody give me a hint or a link on how I should do this?
You can call view.setVisibility(View.GONE) if you want to remove it from the layout.
Or view.setVisibility(View.INVISIBLE) if you just want to hide it.
From Android Docs:
INVISIBLE
This view is invisible, but it still takes up space for layout purposes. Use with setVisibility(int) and android:visibility.
GONE
This view is invisible, and it doesn't take any space for layout purposes. Use with setVisibility(int) and android:visibility.
Try this:
linearLayout.setVisibility(View.GONE);
Kotlin Solution
view.isVisible = true
view.isInvisible = true
view.isGone = true
// For these to work, you need to use androidx and import:
import androidx.core.view.isVisible // or isInvisible/isGone
Kotlin Extension Solution
If you'd like them to be more consistent length, work for nullable views, and lower the chance of writing the wrong boolean, try using these custom extensions:
// Example
view.hide()
fun View?.show() {
if (this == null) return
if (!isVisible) isVisible = true
}
fun View?.hide() {
if (this == null) return
if (!isInvisible) isInvisible = true
}
fun View?.gone() {
if (this == null) return
if (!isGone) isGone = true
}
To make conditional visibility simple, also add these:
fun View?.show(visible: Boolean) {
if (visible) show() else gone()
}
fun View?.hide(hide: Boolean) {
if (hide) hide() else show()
}
fun View?.gone(gone: Boolean = true) {
if (gone) gone() else show()
}
I got a doubt regarding pre-selecting(setSelectedIndex(index)) an item in a ListBox, Im using Spring + GWT.
I got a dialog that contains a panel, this panel has a FlexPanel, in which I've put a couple ListBox, this are filled up with data from my database.
But this Panel is for updates of an entity in my database, thus I wanted it to pre-select the current properties for this items, allowing the user to change at will.
I do the filling up in the update method of the widget.
I tried setting the selectedItem in the update method, but it gives me an null error.
I've searched a few places and it seems that the ListBox are only filled at the exact moment of the display. Thus pre-selecting would be impossible.
I thought about some event, that is fired when the page is displayed.
onLoad() doesnt work..
Anyone have something to help me out in here?
I really think you can set the selection before it's attached and displayed, but you have to have added the data before you can select an index. If this is a single select box you could write something like this:
void updateListContent(MyDataObject selected, List<MyDataObject> list){
for (MyDataObject anObject : list) {
theListBox.addItem(anObject.getTextToDisplay(), anObject.getKeyValueForList());
}
theListBox.setSelectedIndex(list.indexOf(selected));
}
If this is a multiple select box something like this may work:
void updateListContent(List<MyDataObject> allSelected, List<MyDataObject> list){
for (MyDataObject anObject : list) {
theMultipleListBox.addItem(anObject.getTextToDisplay(), anObject.getKeyValueForList());
}
for (MyDataObject selected : allSelected) {
theMultipleListBox.setItemSelected(list.indexOf(selected), true);
}
}
(Note I haven't actually compiled this, so there might be typos. And this assumes that the selected element(s) is really present in the list of possible values, so if you cant be sure of this you'll need to add some bounds checking.)
I've been happily setting both the values and the selection index prior to attachment so as far as I'm aware it should work. There's a bug however when setting the selected index to -1 on IE, see http://code.google.com/p/google-web-toolkit/issues/detail?id=2689.
private void setSelectedValue(ListBox lBox, String str) {
String text = str;
int indexToFind = -1;
for (int i = 0; i < lBox.getItemCount(); i++) {
if (lBox.getValue(i).equals(text)) {
indexToFind = i;
break;
}
}
lBox.setSelectedIndex(indexToFind);
}
Pre-selection should work also with setValue()-function. Thus, no complicated code is needed.