Restricting Nested Scroll View to stop scrolling when the content is not needed to be scrolled - android-collapsingtoolbarlayout

I am implementing an activity with article view like this
What I am trying to do is ... if the content is not necessary to be scrollable , I want to limit the scrolling behaviour of Collapsing Tool bar ( Image View ) & NestedScrollView with its child relative layout(Green one).
Collapsing Tool bar layout has been stopped scrolling successfully when there's no content to scroll .
But when the nestedScrollView is scrolled even if the content is too small to be scrolled and that nestedScrollView is causing to scroll the appbarLayout.
So how can I stop scrolling the nestedScrollView if there is no content to be scrolled as in this picture?
This is what I have Tried.
private void adjustContentSize(double contentHeight) {
int totalScreenHeight = getScreenHeight(this, 1);
showLog("initial Content height -> " + contentHeight / totalScreenHeight);
if (contentHeight > (totalScreenHeight * 0.35) && contentHeight < (totalScreenHeight * 0.45)) {
double contentHeightPercentage = round(contentHeight / totalScreenHeight, 4) + 0.0001;
double appBarHeightPercentage = 1 - contentHeightPercentage;
binding.newsContentView.setMinimumHeight((int) (totalScreenHeight * contentHeightPercentage));
binding.newsHeadIv.getLayoutParams().height = (int) (totalScreenHeight * appBarHeightPercentage);
unlockAppBarOpen(binding.articleAppBarLayout, 1);
showLog("-----------------Content Height : " + contentHeightPercentage + " , Appbar Height : " + appBarHeightPercentage);
changeAppbarLayoutDraggableBehavior(binding.articleAppBarLayout, false);
} else {
showLog("---------------------------------UnAdjustable content------------------------------------");
}
}
private void measureContentSize() {
double contentHeight = binding.newsContentView.getMeasuredHeight();
double totalScreenSize = getScreenHeight(this, 1);
double contentPercentage = contentHeight / totalScreenSize;
if (contentPercentage < 0.35) {
binding.newsContentView.getLayoutParams().height = getScreenHeight(this, 0.35);
changeAppbarLayoutDraggableBehavior(binding.articleAppBarLayout, false);
} else if (contentPercentage == 0.35) {
changeAppbarLayoutDraggableBehavior(binding.articleAppBarLayout, false);
} else {
adjustContentSize(contentHeight);
}
}
I have called measureContentSize() method after I have set the data to the layout.

Related

fabricjs on retina: new object jumps to left top

I continue my work on collaborative sketch tool and trying to add retina devices support. Currently i have following behavior if user creating drawing on ipad air:
small movie
Here is my code:
this.getZoomLevel = function (height) {
if (height > 1024) {
return 1024 / height;
} else {
return height / 1024;
}
};
this.calculateCanvasSize = function(pHeight, pWidth) {
var result = {
height: 0,
width: 0
};
while (result.width < pWidth - 1 && result.height < pHeight - 1) {
result.height = result.height + 1;
result.width = result.height * 4 / 3;
}
return result;
};
this.initCanvas = function () {
try {
var parent = document.getElementsByClassName('komaso-canvas-container')[0];
var canvasSize = this.calculateCanvasSize(parent.clientHeight, parent.clientWidth);
var canvasHtml = "<div id='wrapper-" + this.Id + "' class='whiteboard-canvas-wrapper' data-ng-show='CurrentPage.Id==" + this.Id + "'><canvas width='" + canvasSize.width + "' height='" + canvasSize.height + "' id='whiteboard-" + this.Id + "' class='whiteboard'><p>Your brower does not support Canvas/p></canvas></div>";
$(parent).append($compile(canvasHtml)(scope));
this.Canvaso = document.getElementById(this.HtmlId);
if (!this.Canvaso) {
console.log('Error: Cannot find the imageView canvas element!');
return;
}
if (!this.Canvaso.getContext) {
console.log('Error: no canvas.getContext!');
return;
}
this.FabricCanvas = new fabric.Canvas(this.HtmlId, { selectionColor: 'transparent' });
this.FabricCanvas.setWidth(canvasSize.width);
this.FabricCanvas.setHeight(canvasSize.height);
fabric.Object.prototype.transparentCorners = false;
this.FabricCanvas.on('mouse:down', this.onMouseDown);
this.FabricCanvas.on('mouse:up', this.onMouseUp);
this.FabricCanvas.on('mouse:move', this.onMouseMove);
this.FabricCanvas.on('object:added', this.onObjectAdded);
this.FabricCanvas.on('text:editing:exited', self.onTextObjectEdited);
if (window.devicePixelRatio !== 1) {
var c = this.FabricCanvas.getElement();
var w = c.width, h = c.height;
c.setAttribute('width', w * window.devicePixelRatio);
c.setAttribute('height', h * window.devicePixelRatio);
$(c).width(canvasSize.width);
$(c).height(canvasSize.height);
c.getContext('2d').scale(window.devicePixelRatio, window.devicePixelRatio);
}
this.FabricCanvas.setZoom(this.getZoomLevel(this.Canvaso.height));
this.ToggleTool(self.CurrentTool.ToolName);
this.WhiteboardInitiated = true;
} catch (e) {
console.log(e);
}
};
getZoomLevel returns value to pass into SetZoom method of fabric js canvas object. We decided to have all clients canvas aspects are 4:3 and default dimension is 1024*768. So based on this dimensions we calculation zoom factor.
calculateCanvasSize - returns width and height for canvas according to 4:3 rule.
If you have any idea about how to fix this wrong behavior then post your comment please. Thank you in advance!
I would suggest you yo update to a retina enabled version of fabricjs (grab 1.6.2).
If, for any reason you can't, i think the problem is here:
if (window.devicePixelRatio !== 1) {
var c = this.FabricCanvas.getElement();
...
c.getContext('2d').scale(window.devicePixelRatio, window.devicePixelRatio);
}
getContext return a new context. This is not the context where fabric is gonna render later. If you want to have retina enabled lowerCanvas you have to scale this.FabricCanvas.contextContainer that gets created and referenced on fabric.Canvas initialization.
I suggest you to switch to newer fabric anyway.

How to position text over resizable imageview?

It has a stackpane and few childs inside it:
public class SlideFromText {
private StackPane sp = new StackPane();
private ImageView iv = new ImageView();
private int lines_count = 0;
private Group text_group = new Group();
public SlideFromText(Image img, String t) {
iv.setImage(img);
iv.setPreserveRatio(true);
iv.fitWidthProperty().bind(sp.widthProperty());
iv.fitHeightProperty().bind(sp.heightProperty());
sp.setStyle("-fx-border-color : red; -fx-border-width: 1; -fx-border-style: solid;");
sp.setAlignment(Pos.CENTER);
sp.setMinSize(0, 0);
sp.getChildren().add(iv);
String lines[] = t.split("\\r?\\n");
double height = 0;
for (String line : lines) {
Text text = new Text(line);
text.setFill(Color.BLACK);
text.setY(height);
text_group.getChildren().add(text);
lines_count++;
height += text.getBoundsInLocal().getHeight();
System.out.println("Height: " + height);
}
sp.getChildren().add(text_group);
iv.boundsInParentProperty().addListener(new ChangeListener<Bounds>() {
#Override
public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
Node node = sp.getChildren().get(1);
if (node.getClass() != Group.class) {
return;
}
Group group_node = (Group) node;
double scale_x = iv.getBoundsInParent().getWidth() / group_node.getBoundsInParent().getWidth();
double scale_y = iv.getBoundsInParent().getHeight() / group_node.getBoundsInParent().getHeight();
double scale = Math.min(scale_x, scale_y);
group_node.setScaleX(group_node.getScaleX() * scale);
group_node.setScaleY(group_node.getScaleY() * scale);
System.out.println("IVB: " + iv.getBoundsInParent());
System.out.println("GVB: " + group_node.getBoundsInParent());
}
});
}
public Pane getPane() {
return sp;
}
}
I need to have multi-line text inside group. I want to resize my window and keep image aspect ratio and text proportions and position inside image.
In my example I can't set my text on the top of image.
Maybe it has more easy way.

Binding TextArea height to its content

JavaFX: Is it possible to bind TextArea height (row count) to the height of its content?
I would like to dynamically change height of TextArea while writing the text.
Have a look at JavaFX utility class. Although this is not a solution using binding, computeTextHeight(Font font, String text, double wrappingWidth) method can help you.
This is an exact, simple & working solution:
SimpleIntegerProperty count = new SimpleIntegerProperty(20);
int rowHeight = 10;
txtArea.prefHeightProperty().bindBidirectional(count);
txtArea.minHeightProperty().bindBidirectional(count);
txtArea.scrollTopProperty().addListener(new ChangeListener<Number>(){
#Override
public void changed(ObservableValue<? extends Number> ov, Number oldVal, Number newVal) {
if(newVal.intValue() > rowHeight){
count.setValue(count.get() + newVal.intValue());
}
}
});
Alternatively you can use lambdas to simply the syntax even further:
SimpleIntegerProperty count=new SimpleIntegerProperty(20);
int rowHeight = 10;
textArea.prefHeightProperty().bindBidirectional(count);
textArea.minHeightProperty().bindBidirectional(count);
textArea.scrollTopProperty().addListener((ov, oldVal, newVal) -> {
if(newVal.intValue() > rowHeight){
count.setValue(count.get() + newVal.intValue());
}
});
A solution that workq fine in javafx8 (hiding toolbar is inspired from JavaFX TextArea Hiding Scroll Bars):
class MyTextArea extends TextArea {
#Override
protected void layoutChildren() {
super.layoutChildren();
ScrollBar scrollBarv = (ScrollBar) this.lookup(".scroll-bar:vertical");
if (scrollBarv != null) {
System.out.println("hiding vbar");
((ScrollPane) scrollBarv.getParent()).setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
}
ScrollBar scrollBarh = (ScrollBar) this.lookup(".scroll-bar:horizontal");
if (scrollBarh != null) {
System.out.println("hiding hbar");
((ScrollPane) scrollBarh.getParent()).setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
}
}
#Override
protected double computePrefWidth(double width) {
Bounds bounds = getTextBounds();
Insets insets = getInsets();
double w = Math.ceil(bounds.getWidth() + insets.getLeft() + insets.getRight());
return w;
}
#Override
protected double computePrefHeight(double height) {
Bounds bounds = getTextBounds();
Insets insets = getInsets();
double h = Math.ceil(bounds.getHeight() + insets.getLeft() + insets.getRight());
return h;
}
//from https://stackoverflow.com/questions/15593287/binding-textarea-height-to-its-content/19717901#19717901
public Bounds getTextBounds() {
//String text = (textArea.getText().equals("")) ? textArea.getPromptText() : textArea.getText();
String text = "";
text = this.getParagraphs().stream().map((p) -> p + "W\n").reduce(text, String::concat);
text += "W";
helper.setText(text);
helper.setFont(this.getFont());
// Note that the wrapping width needs to be set to zero before
// getting the text's real preferred width.
helper.setWrappingWidth(0);
return helper.getLayoutBounds();
}
}

Array of Images

I'm working on a blackberry project and for that I need to create grid layout. I'm working on "Blackberry java sdk".
I'm using this code
public class GridScreen extends UiApplication {
// main method
public static void main(String[] args) {
GridScreen theApp = new GridScreen();
UiApplication.getUiApplication().pushScreen(new GFMScreen());
theApp.enterEventDispatcher();
}
}
// VFM
class GFMScreen extends MainScreen {
public GFMScreen() {
// this doesnt do anything for VCENTER!!
//super(Field.USE_ALL_HEIGHT);
// create a grid field manager, with 2 cols and 0 style param for super class
// style of Manager.FIELD_VCENTER | Field.USE_ALL_HEIGHT doesnt do a thing!
int columns = 2;
final GridFieldManager gfm = new GridFieldManager(columns, 0);
// add some items to the screen
int size = 6;
BitmapField[] fRay = new BitmapField[size];
for (int i = 0; i < size; i++) {
// create an bitmap field that's centered H + V (inside grid space)
fRay[i] = new BitmapField(loadBitmap("images/" + (i + 1) + ".png"),
Field.FIELD_HCENTER | Field.FIELD_VCENTER | Field.FOCUSABLE);
gfm.add(fRay[i]);
}
// set padding on top/bottom
{
// add gfm to screen - this does not center the gfm on the screen... is top aligned no matter what!
add(gfm);
int gfmHeight = 48 * (size / columns);
int borderHeight = (Display.getHeight() - gfmHeight) / 2;
gfm.setBorder(BorderFactory.createSimpleBorder(
new XYEdges(borderHeight, 0, borderHeight, 0),
Border.STYLE_TRANSPARENT));
System.out.println("border=" + borderHeight);
System.out.println("display=" + Display.getHeight());
System.out.println("gfm=" + gfmHeight);
}
}
/** #param res eg "images/icon.png" */
public static Bitmap loadBitmap(String res) {
EncodedImage img = EncodedImage.getEncodedImageResource(res);
return img.getBitmap();
}
}// end class
What is wrong in this code?
Is there any best approch to create grid layout in BlackBerry.
In above code error is "Display.getHeight() is not define".
Hope this code helps:
Bitmap[] images = new Bitmap[6];
for ((int i = 0; i < 6; i++) {
string filename = "images/" + String.valueOf(i + 1) + ".png";
images[i] = Bitmap.getBitmapResource(filename);
}
}

Creating Tabmenu in j2me

Is there any way to create a Tab Menu in j2me?
I found a code but I am unable to understand it
In this code there is Tab Menu created which is in Canvas class and then Tab menu is created which is totally done in Canvas or painted. The only part I found difficult to grasp was the void go() method and then
When I try to draw anything above and below this code using paint method, it doesn't work - what's the problem?
Below is the code
// Tab Menu CANVAS class
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
public class TabMenuCanvas extends Canvas
{
TabMenu menu = null;
public TabMenuCanvas()
{
menu = new TabMenu(
new String[]{"Home", "News", "Community", "Your files", "Credits", "Events", "Blog", "Upload", "Forum Nokia"},
getWidth() - 20
);
}
protected void keyPressed(int key)
{
int gameAction = getGameAction(key);
if(gameAction == Canvas.RIGHT)
{
menu.goRight();
repaint();
}
else if(gameAction == Canvas.LEFT)
{
menu.goLeft();
repaint();
}
}
protected void paint(Graphics g)
{
g.translate(10, 30);
menu.paint(g);
g.translate(- 10, - 30);
}
}
// Tab Menu Class
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
public class TabMenu
{
int background = 0xffffff;
int bgColor = 0xcccccc;
int bgFocusedColor = 0x0000ff;
int foreColor = 0x000000;
int foreFocusedColor = 0xffffff;
int cornerRadius = 6;
int padding = 2;
int margin = 2;
Font font = Font.getDefaultFont();
int scrollStep = 20;
int selectedTab = 0; //selected tab index
int[] tabsWidth = null; //width of single tabs
int[] tabsLeft = null; //left X coordinate of single tabs
int tabHeight = 0; //height of tabs (equal for all tabs)
String[] tabs = null; //tab labels
int menuWidth = 0; //total menu width
int viewportWidth = 0; //visible viewport width
int viewportX = 0; //current viewport X coordinate
public TabMenu(String[] tabs, int width)
{
this.tabs = tabs;
this.viewportWidth = width;
initialize();
}
void initialize()
{
tabHeight = font.getHeight() + cornerRadius + 2 * padding; //[ same for all tabs]
menuWidth = 0;
tabsWidth = new int[tabs.length];
tabsLeft = new int[tabs.length];
for(int i = 0; i < tabsWidth.length; i++)
{
tabsWidth[i] = font.stringWidth(tabs[i]) + 2 * padding + 2 * cornerRadius;
tabsLeft[i] = menuWidth;
menuWidth += tabsWidth[i];
if(i > 0)
{
menuWidth += margin;
}
}
}
public void goRight()
{
go(+1);
}
public void goLeft()
{
go(-1);
}
private void go(int delta)
{
int newTab = Math.max(0, Math.min(tabs.length - 1, selectedTab + delta));
boolean scroll = true;
if(newTab != selectedTab && isTabVisible(newTab))
{
selectedTab = newTab;
if( (delta > 0 && tabsLeft[selectedTab] + tabsWidth[selectedTab] > viewportX + viewportWidth) ||
(delta < 0 && tabsLeft[selectedTab] < viewportX))
{
scroll = true;
}
else
{
scroll = false;
}
}
if(scroll)
{
viewportX = Math.max(0, Math.min(menuWidth - viewportWidth, viewportX + delta * scrollStep));
}
}
private boolean isTabVisible(int tabIndex)
{
return tabsLeft[tabIndex] < viewportX + viewportWidth &&
tabsLeft[tabIndex] + tabsWidth[tabIndex] >= viewportX;
}
public void paint(Graphics g)
{
int currentX = - viewportX;
g.setClip(0, 0, viewportWidth, tabHeight);
g.setColor(background);
g.fillRect(0, 0, viewportWidth, tabHeight);
for(int i = 0; i < tabs.length; i++)
{
g.setColor(i == selectedTab ? bgFocusedColor : bgColor);
g.fillRoundRect(currentX, 0, tabsWidth[i], tabHeight + cornerRadius, 2 * cornerRadius, 2 * cornerRadius);
g.setColor(i == selectedTab ? foreFocusedColor : foreColor);
g.drawString(tabs[i], currentX + cornerRadius + padding, cornerRadius + padding, Graphics.LEFT | Graphics.TOP);
currentX += tabsWidth[i] + margin;
}
}
}
When I try to draw anything above and below this code using paint method, it doesn't work
what of the paint methods you use to draw above and below? Pay attention that there are two methods named that way - first is in TabMenuCanvas, second is in TabMenu (second method is invoked from TabMenuCanvas#repaint).
whatever you would try to draw in TabMenuCanvas#paint will most likely be overwritten by setClip and fillRect when TabMenu#paint is invoked following repaint request
The only place where one can expect to be able to draw something visible seems to be in TabMenu#paint method, inside the clip area that is set there.
You can use GUI Libraries for J2ME,for example Lightweight User Interface Toolkit (LWUIT),Flemil have "tab menu".You can see list of GUI Libraries here.

Resources