React-Native Element changing size while scrolling - android

I'm trying to make a react-native scrollview with 3 (or more) elements where the element in the middle of the screen is always 1.75 times the normal element size, and while scrolling the size changes dynamically. Can I find when the element is in the center of screen if the size of the scrollview will be changing? Is it possible to do without some complicated mathematical approach?
I was trying putting conditions to all elements' styles but can't find a way to determine when the condition is met.
handleScroll(event) {
var x = event.nativeEvent.contentOffset.x;
var page = x / this.state.totalWidth;
this.setState({ position: page })
}
isElementFocused(start, stop) {
return (this.state.position >= start && this.state.position < stop);
}
Element:
<View style={styles.swipeBox,
{
backgroundColor: this.isElementFocused(1, 2) ? this.getColor(1) : colors.primary,
width: this.isElementFocused(1, 2) ? this.getWidth(1) : this.state.baseWidth,
height: this.isElementFocused(1, 2) ? this.getHeight(1) : this.state.baseHeight,
}}>
<Text>test</Text>
</View>

I think you want to use smoothScrollToPosition()
please visit https://www.programcreek.com/java-api-examples/?class=android.support.v7.widget.RecyclerView&method=smoothScrollToPosition

Related

Jetpack compose IntrinsicSize.Min cuts off Text - want to force Text to take up exact height and minimum width required for that height

I have a Text component that I want the width to expand as big as it wants to accommodate the supplied text and to be exactly 2 lines tall.
I have attempted to implement this by calculating the height using my font size and the number of lines that I want:
val textHeight = textStyle.lineHeight.value * 2
Then, based on various articles (such as this one https://www.answertopia.com/jetpack-compose/jetpack-compose-intrinsicsize-tutorial/) and what I understand of IntrinsicSize, shouldn't I be able to constrain the height and use IntrinsicSize.Min to set the text's width to fit everything at the minimum width required? This actually just cuts off the text.
Text(
modifier = Modifier.height(textHeight).width(IntrinsicSize.Min),
text = "Fabrication et assemblage soignes",
style = textStyle,
)
For some reason ends up rendering as
I want it to look like
Fabrication et
assemblage soigne
On two lines, wrapped to the minimum width.
How can I achieve the result I want?
Also note using .wrapContentWidth() doesn't work because then the text just takes up 1 line and leaves the extra height space empty.
If it's just for that specific text you want, which I highly doubt, you could insert a line break inside the string as follows: "Fabrication et\nassemblage soignes".
If it's for more general sentences, then it's not clear how you would want the Text component to distribute the words between the two lines.
Assuming you would want the width of the lines to be as close as possible (like this strategy), the most 'elegant' way I can think of (which is not very elegant) is implementing an algorithm which would measure the entire width of the text, find the whitespace closest to the middle and replace it with a line break.
I've implemented something simpler which does manage to divide at the position you want:
fun String.attemptToDivideEqually(): String {
if (this.length <= 2) return this
val idealLineBreakIndex = this.closestWhiteSpaceToIndex((this.length + 1) / 2) ?: return this
return this.substring(0, idealLineBreakIndex) + "\n" + this.substring(
idealLineBreakIndex + 1,
this.length
)
}
fun String.closestWhiteSpaceToIndex(index: Int): Int? {
if (index !in 0 .. this.lastIndex) return null
val maxDistance = maxOf(index, this.lastIndex - index)
for (i in 0 .. maxDistance) {
if (index + i <= this.lastIndex && this[index + i] == ' ') return index + i
if (index - i >= 0 && this[index - i] == ' ') return index - i
}
return null
}
However, I don't recommend using it in production code for the following reasons:
Characters can differ greatly in width, so if for whatever reason, the first 'half' of the string has significantly more 'narrow' letters, than the latter, it may look odd.
If there are only a few number of words, it may look odd.
There are probably more reasons I cannot currently think of + I have not tested it thoroughly.
It was an interesting question nonetheless!

Are there any alternatives to adjustsFontSizeToFit for Android?

I am using flex in Text field to display my values/range. For IOS I am using the properties adjustsFontSizeToFit and minimumFontScale props for Text to achieve the ideal font size and scaling. I want the same scaling to be enabled for Android. Does anyone use any tricks for Android?
<View style={{flex: 40}}>
{
(Platform.OS === 'ios') ?
<Text style={{flex: 1, paddingRight: 2}} adjustsFontSizeToFit
minimumFontScale={0.5}>
//if decimal value exists show range
(pointFivePart_1 === '5') ?
<Text style={{ flexDirection: 'row' }} >
<Text style={styles.mainValueStyle}>{first_1}</Text>
<Text style=styles.decimalValueStyle}> .pointFivePart_1}</Text>
<Text style={styles.mainValueStyle}>°</Text>
</Text>
: <Text style={styles.mainValueStyle} >{min}°</Text>
}
//if two values then show the second value as range
{// render largest value if different than min
(maxSet === minSet) ? null : (
(pointFivePart_2 === '5') ?
<Text style={{ flexDirection: 'row' }} >
<Text style={styles.mainValueStyle}> - {first_2}</Text>
<Text style={styles.decimalValueStyle}>.{pointFivePart_2}</Text>
<Text style={styles.mainValueStyle}>°</Text>
</Text>
:
<Text style={styles.mainValueStyle} > - {maxSet}°</Text>
)
}
</Text>
:
//same styling for android
Simple but somehow working solution (crossplatform):
fontSize = Math.sqrt(textWidth*textHeight/text.length)
where textWidth, textHeight - size of your Text component, text.length - length of your text.
minimumFontScale can be achieved with
fontSize = Math.max(fontSize,minimumFontSize)
I came to this formula by solving such system of equations:
lettersInLine = textWidth/fontSize
lines = textLength/lettersInLine
lines*fontSize = textHeight
assuming here that font has square sized (width equal to height) letters.
Though this formula makes sense even without equations. You just
calculate square of whole text element
calculate square for each letter (dividing whole square to letters number)
take square root from letter square to get font size
Simply set adjustFontSizeToFit and numberOfLines
DONT SET fontSize
<Text adjustsFontSizeToFit numberOfLines={1}>This text will fit the width of the container</Text>
I am using slightly modified version of #nazar solution. I was not able to make it scale as i needed, text would get cut off, because the dynamic height based on screen device would affect the fontSize too much.
Anyways, here is my solution.
var fontSize = width / text.length;
var maxSize = width / 5;
fontSize = Math.min(fontSize, maxSize);
Maximum font size is defined by 5 letters. Less letters would make too big fontSize in this case. This value can be of course anything. You can make simple function out of this and call it anywhere you need with width parameter, which is idealy something like screen.width * 0.1, second parameter being length of the text and third parameter for the maxSize. So something like this:
export function GetFontSize(width, length, max) {
var fontSize = width / length;
var maxSize = width / max;
fontSize = Math.min(fontSize, maxSize);
return fontSize;
}
#aaltaf In android I generally define dimension of TextView into dimension file inside values and for font generally use default font from fontfamily
here is an example...
<TextView
android:id="#+id/shipment_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/send_two_dp"
android:gravity="center_vertical"
android:text="#{locationViewModel.sameDayShipmentText}"
android:textColor="#color/black"
android:textSize="#dimen/send_fourteen_sp"
android:fontFamily="sans-serif"
tools:text="6-8 hour delivery" />
Hope it will helped :)

Phantom double clicks from MouseArea on Android

While testing out an application on Android I noticed something funky going on. A double click event handler has been triggering without any double clicks occurring on that particular item.
Trying to isolate the issue I discovered that pretty much every chain of clicks rapid as a double click on regardless what two objects would cause the second click on the second object to register as a double click, when in fact it is just a single click.
Below is an example consisting of a row of 3 randomly colored rectangles, each one with a mouse area inside of it. The double click of each mouse area is rigged to set the parent rectangle's color to a different random color. Clicking rapidly two different rectangles under android triggers a double click and a color change for the second. This does not happen on Windows or Ubuntu Linux.
Window {
id: main
visible: true
width: 400
height: 400
title: qsTr("Hello World")
Row {
Rectangle {
width: main.width * .33
height: main.height
color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
border.color: "black"
border.width: 2
MouseArea {
anchors.fill: parent
onDoubleClicked: parent.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
}
}
Rectangle {
width: main.width * .33
height: main.height
color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
border.color: "black"
border.width: 2
MouseArea {
anchors.fill: parent
onDoubleClicked: parent.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
}
}
Rectangle {
width: main.width * .33
height: main.height
color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
border.color: "black"
border.width: 2
MouseArea {
anchors.fill: parent
onDoubleClicked: parent.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
}
}
}
}
It looks as if the "previous click" or whatever property that's supposed to be used to detect double clicks is shared between different mouse areas instead of being per mouse area. The issue manifests in both Qt 5.7 and 5.7.1.
It definitely looks like my 10th discovered Qt bug this year, but I still feel like asking on the odd chance someone knows what's going on and how to fix it, because I need this fixed, and the Qt bugreport process is not speedy. So any ideas are more than welcome.
Until there is a better answer with an actual solution, it may be useful to know that it is possible to somewhat mitigate the devastating effect this issue has on user experience by reducing the global interval for double click detection.
By default it is the rather lethargic 500 msec. I found out that by reducing it to 250 msec helps to avoid over 90% of the incorrect double clicks:
QGuiApplication app(argc, argv);
app.styleHints()->setMouseDoubleClickInterval(250);
Additionally, there is a quick and hacky qml-only way to create a "fixed" copy of MouseArea:
// MArea.qml
Item {
id: main
property alias mouseX : ma.mouseX
property alias mouseY : ma.mouseY
property alias acceptedButtons: ma.acceptedButtons
// etc aliases
signal clicked(var mouse)
signal doubleClicked(var mouse)
// etc signals, function accessors
MouseArea {
id: ma
property real lClick : 0
anchors.fill: parent
onClicked: {
var nc = Date.now()
if ((nc - lClick) < 500) main.doubleClicked(mouse)
else main.clicked(mouse)
lClick = nc
}
}
}
This one actually works as intended and can be made almost entirely "plug and play" compatible with the original one.

Qt Qml - android - adjust listview scroll speed/velocity

[Qt Quick 2.0 (qml) - Android]
I searched but I don't get how one can increase the velocity of the scrolling in a listview:
ListView {
width: 180; height: 200
Component {
id: contactsDelegate
Rectangle {
id: wrapper
width: 180
height: yeah.height
Column{
id:yeah
Text {
id: contactInfo
text: name + ": " + number
}
Image{
source: jpgsrc
}
}
}
}
model: ContactModel {}
delegate: contactsDelegate
focus: true
}
Question
Say my ContactModel has 200 elements. My problem is that the scrolling speed over those elements is too slow. It takes too long to scroll the whole list.
I would like to know how to modify that code to make the scrolling experience faster (at least with a higher velocity).
Thanks
To improve speed of scrolling you can play with 2 ListView properties: cacheBuffer and maximumFlickVelocity.
maximumFlickVelocity directly impacts speed whereas cacheBuffer should be updated if you have speed issues due to slow dynamic loading of ListView elements.

Android WebView getContentHeight() doesnt return the correct value

I have a requirement where I display a WebView with a checkbox beneath it. The checkbox is initially in disabled state. Only when the user scrolls down to the bottom of the webview , the checkbox is enabled. I do this by extending Webview class and writing my onScrollChanged listener as below:
#Override
protected void onScrollChanged(int left, int top, int oldLeft, int oldTop) {
if ( (getContentHeight() - (top + getHeight())) <= mMinDistance )
{
Log.i("MYACT","content height: "+getContentHeight()+" top: "+top+" Height: "+getHeight()+" minDistance: "+mMinDistance);
Log.i("MYACT", "Reached bottom");
mOnBottomReachedListener.onBottomReached(this);
}
else{
Log.i("MYACT","content height: "+getContentHeight()+" top: "+top+" Height: "+getHeight()+" minDistance: "+mMinDistance);
Log.i("MYACT", "Not at bottom");
mOnBottomReachedListener.onNotAtBottom(this);
}
super.onScrollChanged(left, top, oldLeft, oldTop);
}
The problem is the condition
(getContentHeight() - (top + getHeight())) <= mMinDistance) //mMinDistance is 0 in my case
is satisfied even before i scroll down to the bottom of the page. As you can see, I tried printing the values of each in log and found that the parameter "top" sometimes exceeds the value "getContentHeight".
Sample log values:
08-14 11:28:19.401: I/MYACT(1075): content height: 3020 top: 3861
Height: 416 minDistance: 0
How can i make avoid this scenario in this case? Should i use a different way of checking whether i have scrolled down to the bottom of the page?
Thanks
I found the issue with this after some research. Webview usually scales the web page based on the screen size and then renders it. It usually zooms the page so that it doesn't look too small in the phone. You can get this scale factor by using the method getScale()
So, in my case, i would use the following condition to check whether end of page has been reached
(getContentHeight()*getScale() - (top + getHeight())) <= mMinDistance)
//mMinDistance is 0 in my case
If memory serves values returned by getContentHeight() may depend on implementation of a WebView and its rendering mode (software/hardware). But I'm not sure. Perhaps this talk at Google IO will help you more in this question.
But generally speaking it's always hard and tricky to mix WebView with other views, especially when it comes to scrolling.
So my advice would be to put your checkbox into HTML displayed by the WebView. You have pretty much options of doing that like injecting some additional HTML code before passing it to loadData() method or invoking JavaScript with loadUrl("javascript:whatever();"), which can modify the initial DOM structure.
As a rule I do not put other views to Activity window when I have to deal with a WebView there.

Categories

Resources