Open ggunti opened 4 years ago
This is a major issue and is the reason why I want to move both android and iOS to different implementations as mentioned in #25. Behind the scenes this is virtually impossible because of rendering via svg.
Did you play around with the example? I built it exactly for these questions. Please do so, it's worth the time. There's a screen with a growing tylor expression with different layouts using resizeMode=cover/contain
which is the only workaround I could find. This shrinks the text to fit the screen but might not work on iOS.
Happy to hear. I created this library exactly because what you said. And now I know why resizing on iOS doesn't work. That is the behavior I implemented in native, so android resizes to fit the parent when
resizeMode
iscover
. iOS is implemented withreact-native-svg
because I didn't finish the standalone implementation yet.If you want to contribute there's work to do on iOS. I want to move to the standalone implementation. The first thing to do is to handle the measuring of the view in native.
react-native
uses it's own layout flow and at the time I didn't figure it out. After that it's all about exposing props.If you're not an iOS dev you can try to fix this issue for the current implementation. This would require looking into
react-native-svg
.For android I have in mind for the next major version moving to this implementation if it's stable and good, retex, so you can look it to it as well.
It looks like on android the default behavior is resizeMode='contain'
, while on iOS the default is resizeMode='cover'
. Anyhow, I tried to play with resizeMode
on both platforms, but I was not able to automatically split a long math expression into multiple lines.
What I also tried is to automatically fit expression in a single line (it could be an alternative until we could split into multiple lines). As I said above, this is the default behavior on android, but not also on iOS.
If I set resizeMode='contain'
, the long math expressions (which on iOS by default does not fit on the screen), are resized automatically such that to fit in a single line (like on android), like here:
The code:
const App: React.FC<{}> = () => {
return (
<SafeAreaView style={styles.container}>
<View style={styles.mathBox}>
<Text style={{ fontSize: 24, marginRight: 7 }}>Let</Text>
<MathView resizeMode='contain' math={math} />
</View>
</SafeAreaView>
);
};
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
marginHorizontal: 5,
justifyContent: 'center',
},
mathBox: {
flexDirection: 'row',
alignItems: 'flex-end',
flexWrap: 'wrap',
},
});
Although, if I add also config={{ ex: 12 }}
to the MathView
, the bottom is cut down a little bit (only on iOS, on android looks good), as you can see here:
I would like to add also the config={{ ex: 12 }}
option because in case that the math expression is short enough, it will guarantee that it will have a minimum size (12). Also, in case that the math expression is too long, it would be automatically resized to fit on a single line. So, for me, it sounds a not bad idea to combine resizeMode
with config={{ ex: ... }}
, but on iOS it may cut down the bottom, as you can see above.
I will also play a little bit with your examples.
Regarding contribution, do you think that it could be possible to configure / modify react-native-svg
such that to allow us to automatically split a single line math expression into multiple lines?
OK. Good work.
I am not sure how to proceed. This can be handled via mathjax
or react-native-svg
or both.
I tried something out, which isn't so good, but take a look, rnsvg-fix-height
My approach was trying to handle it with viewBox
prop react-native-svg
but I still need to shift it and don't know how to calculate the amount.
rnsvg-fix-height
makes math expression almost invisible (extremely small) on iOS, so something is not okay. See the example below.
The code:
import React from 'react';
import MathView from 'react-native-math-view';
const math = 'x=\\frac{-b\\pm\\sqrt{b^2-4ac}}{2a}';
const App: React.FC<{}> = () => <MathView config={{ ex: 12 }} resizeMode='contain' math={math} />;
export default App;
Result on iOS (actually a very small math expression):
Result on android (it looks nice, just like before):
This is hilarious! How did you notice it up there??
rnsvg-fix-height
makes math expression almost invisible (extremely small) on iOS, so something is not okay. See the example below.Result on iOS (actually a very small math expression):
First time I did not notice. Then, accidentally I observed that actually there is a math expression. :))
Supporting flex-wrap
is major. And I agree that at least resizing is a suitable way to handle UI until then.
So the fork was successfulish. I did change the layout which is GOOD. Maybe try to alter the calculations.
The problem with MathJax is that their documentation is a crazy, daunting labyrinth so it's a guessing game to try to achieve something from there.
Trying via react-native-svg
will require you to dive into their native implementation or dive into svg
tricks. I think this is the most probable approach.
Trying to hack with svg
tricks - hope you succeed, I don't have any ideas besides the one I tried in the fork.
Trying to fix this in native makes sense. I would try extending some class in iOS code and create a native measuring function that receives resizeMode
prop. I don't know how react lays out views in iOS or what's the equivalent to android's ShadowNode
. I would start there.
BTW the native approach is how and why android works
I also have a question, I don't understand completely:
Why when you say native, you actually exclude react-native-svg
? What do you mean by native here? As I see, react-native-svg
uses native code (java android + swift/objective-c iOS) in order to implement svg in react native. Do you think that AndroidSVG library is faster than react-native-svg
?
You are right. It is a native library. I refer to it this way because I intend on having an independent native implementation for this library. AndroidSVG is much faster. You can see the difference in the example app. Try switching the basic view with the svg rendered math view. It does have problems (e.g. changing color blocks the UI thread).
Which leads me to the fact that I failed to mention my favored approach. I didn't get the chance to finish up the native iOS code, if you're up for it. The major thing to do is to pass the measurements to react and the rest is relatively simple. Handling shrinking in such a case would be as simple as applying scale.
Thanks for clarification, I understand. I wonder why react-native-svg
does not use AndroidSVG
(for android) under the hood if it is much faster? Maybe it is less configurable, I don't know...
Actually on iOS native, what you should measure? I'm not an iOS developer, but it has something to do with math? You need to do some calculations in order to measure the layout?
Right again, it's not very configurable. But I read they want to work on it. It's not the math. It's the react part. React handles the entire layout-draw pass on it's own on both platforms so you need to opt in some how (no docs regarding this what so ever, it's simply digging through the code or looking into what other libraries do).
import MathView, { MathText } from 'react-native-math-view';
var a = 'If\ 〖(1+x)〗^15=C_0+C_1x+C_2x^2+...+C_15x^15,\ then\ C_2+2C_3+3C_4+...+14C_15\ is\ equal\ to'; // latex string
var b = a.match(/(.{1,4})/g); // by using specific length to split string for(let jk=0;jk<b.length;jk++){ b[jk]=b[jk]+'$' // using $ symbol goto new line (so add $ symbol) } var textval='$$'+b.join("") // by using $$ in front to view math equation and text
<MathText resizeMode='cover' style={{alignSelf:'center'}} value={textval} />
@znyrsukki Thanks! Interesting solution. It is perhaps the best solution to date. However it will not solve the issue entirely because the rendered svg is not proportional to the string symbol length.
Take a look at #30
I just rendered some math content:
It looks really good:
Then, I made the MathView content longer (I modified only the
const math
):Now, this is what I get:
As you can see, the 'Let' text was automatically moved on a separate line (because of
flexWrap: 'wrap'
), but the math expression is not fully visible (\\frac{5}{6}
is not visible at the end).So, is it possible to configure
MathView
such that automatically shows on multiple lines the math expressions which does not fit in a single line? I would like to get some math expressions from a server and just render them, but some of them may not fit in a single line on the screen, so it would be very useful ifMathView
could automatically split long expressions into multiple lines.