I'm developing an android project and I want to render some chemistry formula.
I wrote the following code and I got the following result.
I create a custom string and show it in a textview.
But my question is this: Is this the best way to do this? And is there another way to handle that?
str = new SpannableString(Html.fromHtml("2H<sup>+</sup> + So<sub size = 2>4</sub><sup size = 2>2-</sup> --> H<sub size =2>2</sub>So<sub size = 2>4</sub>"));
ss1.setSpan(new RelativeSizeSpan(0.6f), 2,3, 0); // set size
ss1.setSpan(new RelativeSizeSpan(0.6f), 8,11, 0); // set size
ss1.setSpan(new RelativeSizeSpan(0.6f), 17,18, 0); // set size
ss1.setSpan(new RelativeSizeSpan(0.6f), 20,21, 0); // set size
TempF.setText(ss1,TextView.BufferType.SPANNABLE);
I don't think there is a better way.
Unfortunately Html.fromHtml() ignores <font size="n"> tags, so these spans need to be added manually, as you have done.
I had a similar problem to solve. I created a simple library by extending WebView and using JavaScript in the background. https://github.com/RanaRanvijaySingh/EquationView
String strChem = "Chemistry: \\(\\ce{CO2 + C -> 2 CO}\\)";
EquationView equationViewChem = findViewById(R.id.equationViewChem);
equationViewChem.setText(strChem);
In your layout file:
<com.rana.equationview.EquationView
android:id="#+id/equationViewChem"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
Hope this helps someone.
I think you have found a solution that fits you.
Perhaps, if there is a rule to know when a symbol will be a subscript or superscript, or the spansize you have to use, you can write a method to parse a given a formula privided as a string and automatically provide the formated html output.
To do this, and assuming there are specific rules, you can use a finite state machine that will "compile" a text string to the html output you need.
If you are looking for something like this let me know and we may be able to work it out.
Another option would be to see if you find (in Internet) a font that meets your needs (Or perhaps build your own). You can import a font putting the font file in the assets folder and setting it from there in the source.
Related
I have video player in my android app and I make them using exoplayer library. My player can to play .m3u8 videos (I obtain them from backend) and all of them can be in different quality, for example, 1024x576, 768x432, etc. I want to show for user dialog with possibility to change video stream quality. For this i use the next code from exoplayer samples in github:
MappingTrackSelector.MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
if (mappedTrackInfo != null) {
CharSequence title = "Tit;eee";
int rendererIndex = 0; // renderer for video
int rendererType = mappedTrackInfo.getRendererType(rendererIndex);
boolean allowAdaptiveSelections =
rendererType == C.TRACK_TYPE_VIDEO
|| (rendererType == C.TRACK_TYPE_AUDIO
&& mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_VIDEO)
== MappingTrackSelector.MappedTrackInfo.RENDERER_SUPPORT_NO_TRACKS);
Pair<AlertDialog, TrackSelectionView> dialogPair =
TrackSelectionView.getDialog(this, title, trackSelector, rendererIndex);
dialogPair.second.setShowDisableOption(true);
dialogPair.second.setAllowAdaptiveSelections(allowAdaptiveSelections);
dialogPair.first.show();
}
and it works okay. But, i need to customize this dialog, for example deleting "none" option and making ALL elements single choice only. How can I make this?
This might be late but here are the ways to do so,
Here the main Class that does all these awesome stuff is "TrackSelectionView", this class simply extends a LinearLayout. To achieve your desired features you need to make your own class (name is anything) and then just copy paste the entire code of TrackSelectionView in it. Why are we doing so? coz, we need to change some logic of that class and it's a read-only class.
Actually to achieve the first feature (no "none" option) you simply can write dialogPair.second.setShowDisableOption(false); instead of that "true".
Writing our own class and copy-paste code is for the second feature.
In "TrackSelectionView" it uses a 2-D array to store the CheckedTextView. For the first two togglebuttons (Auto and None) it uses CheckedTextView separately but for all other resolution, CheckedTextView is getting stored in that 2-D array.
I won't post the entire codebase here as it will make things messy, I have created a github.gist file, you can get a reference from there...
https://gist.github.com/abhiint16/b473e9b1111bd8bda4833c288ae6a1b4
Don't forget to use your class reference instead of TrackSelectionView.
You will use this above file as shown in this Gist
https://gist.github.com/abhiint16/165449a1a7d1a55a8f69d23718c603c2
The Gist file makes the selection "Single-select" and in addition to that it also performs an awesome stuff for you in case you need it in your ExoPlayer,
Here, the actual video format that you get is in 512 X 288, 0.57 Mbps format in a list, I'm just mapping predefined Low, Medium, High etc with the index of list. You can try your own way.
So when you click on one of the resolution, it transforms the textview of your exoplayer for the selected-resolution ("L" for "Low").
For that you just need to implement an Interface named GetReso in your Class and there you'll get the selected text-initial. Now you can just set that string to a textview.
Enjoy coding.....
For anyone seeing this after 2021, it took me quite a while to achieve a similar scenario in demo application of Exoplayer. So, I've decided to share how I solved it.
Use the below code inside TrackSelectionDialog file.
TrackNameProvider trackNameProvider = new DefaultTrackNameProvider(getResources());
TrackSelectionView trackSelectionView = rootView.findViewById(R.id.exo_track_selection_view);
trackSelectionView.setTrackNameProvider(f -> f.height != Format.NO_VALUE ? (Math.round(f.frameRate) + " FPS, " + (f.bitrate == Format.NO_VALUE ? "" : (getResources().getString(R.string.exo_track_bitrate, f.bitrate / 1000000f)) ) + ", " + f.height + " P"): trackNameProvider.getTrackName(f));
This will show video tracks as "25 FPS, 2.11 Mbps, 720P". You can modify it in any way you want.
Important to note that it will keep the default formatting for audio and text tracks.
By code, I can make a button that inserts these 3 emojis into the text: ⚽️😈🐺
On many phones when the user clicks the button, though, the problem is that ⚽️😈🐺 displays as [X][X][X]. Or even worse, it displays only three empty spaces.
I would like to disable and hide my own built-in emoji-keypad on Android devices that do not display emojis correctly. Does anyone knows or have a tip on how to detect in code if a device has emoji support?
I have read that emoji is supported from android 4.1, but that is not my experience....
I just implemented a solution for this problem myself. The nice thing with Android is that it is open source so that when you come around problems like these, there's a good chance you can find an approach to help you.
In the Android Open Source Project, you can find a method where they use Paint.hasGlyph to detect whether a font exists for a given emoji. However, as this method is not available before API 23, they also do test renders and compare the result against the width of 'tofu' (the [x] character you mention in your post.)
There are some other failings with this approach, but it should be enough to get you started.
Google source:
https://android.googlesource.com/platform/packages/inputmethods/LatinIME/+/master/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java#441
https://android.googlesource.com/platform/packages/inputmethods/LatinIME/+/master/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
Based on Jason Gore answer:
For example create boolean canShowFlagEmoji:
private static boolean canShowFlagEmoji() {
Paint paint = new Paint();
String switzerland = "\uD83C\uDDE8\uD83C\uDDED"; // Here enter Surrogates of Emoji
try {
return paint.hasGlyph(switzerland);
} catch (NoSuchMethodError e) {
// Compare display width of single-codepoint emoji to width of flag emoji to determine
// whether flag is rendered as single glyph or two adjacent regional indicator symbols.
float flagWidth = paint.measureText(switzerland);
float standardWidth = paint.measureText("\uD83D\uDC27"); // U+1F427 Penguin
return flagWidth < standardWidth * 1.25;
// This assumes that a valid glyph for the flag emoji must be less than 1.25 times
// the width of the penguin.
}
}
And then in code whenever when you need to check if emoji is available:
if (canShowFlagEmoji()){
// Code when FlagEmoji is available
} else {
// And when not
}
Surrogates of emoji you can get here, when you click on detail.
An alternative option might be to include the Android "Emoji Compatibility" library, which would detect and add any required Emoji characters to apps running on Android 4.4 (API 19) and later: https://developer.android.com/topic/libraries/support-library/preview/emoji-compat.html
final Paint paint = new Paint();
final boolean isEmojiRendered;
if (VERSION.SDK_INT >= VERSION_CODES.M) {
isEmojiRendered = paint.hasGlyph(emoji);
}
else{
isEmojiRendered = paint.measureText(emoji) > 7;
}
The width > 7 part is particularly hacky, I would expect the value to be 0.0 for non-renderable emoji, but across a few devices, I found that the value actually ranged around 3.0 to 6.0 for non-renderable, and 12.0 to 15.0 for renderable. Your results may vary so you might want to test that. I believe the font size also has an effect on the output of measureText() so keep that in mind.
The second part was answerd by RogueBaneling here how can I check if my device is capable to render Emoji images correctly?
I'm running a Python script under Windows which deals with 480x800 PNG images with 32-bit depth. I need to check if the given image is fully black or not. After some searching I've found that ImageMagick could help me to achieve this but unfortunately there's no manual for such task.
So a more general question is how to check if the image consists only of one color?
Edit:
My apologies for not providing all the information about the environment from beginning. The python script is executed using Android's monkeyrunner. Since it uses it's own instance of Jython (version 2.5) it's not possible to use any modules from external libraries. Inside there's a MonkeyImage class to work with screenshots taken from the device. So I adopted #eumiro's answer for it.
import Image
im = Image.load("image.png")
diff_colors = list(set(im.getdata()))
if len(diff_colors) == 1 and diff_colors[0] == (0, 0, 0):
print "all black"
EDIT as #JonClements proposes, this will be faster and stop as soon as anything else than black is found:
import Image
im = Image.load("image.png")
if all(rgb == (0,0,0) for rgb in im.getdata()):
print "all black"
I am no expert in Python but I saw that there is a PNG module that you can use.
Load the PNG and export it to an RGB(A) array.
Checking if it is totally black should then be simple. Run through the array and make sure nothing differs from 0.
I think this should work.
Out of curiosity, why would you want to check if the image is black?
In my current project I need my users to be able to scroll over and zoom in on large SVG
Images. A major problem i encountered though, is the limit the android WebView class puts on zooming in and out. Is there any way I can remove or change these limits to my own likings?
The standard zoom controls do not seem to support releasing these boundries.
If my question is unclear, or if I need to elaborate on my question do not hesitate to ask.
Greets,
Wottah
Since no one seems to have come up with a different solution than using reflection - I'm not aware of any alternatives at this point - I wrote up a quick code snippet that illustrates how to bypass the upper limit on the zoom-in action.
Note that the code below will only work on ICS, and possibly Honeycomb, but I currently don't have a tablet lying around to inspect if the inner workings rely on the same ZoomManager class. Gingerbread, Froyo and Eclair all appear to implement the zooming functionality more or less directly in the WebView class. With the example below it should be fairly easy to add some code to also take those operating systems into account.
// just set an Activity's content view to a single WebView for this test
WebView mWebview = new WebView(this);
setContentView(mWebview);
// retrieve the ZoomManager from the WebView
Class<?> webViewClass = mWebview.getClass();
Field mZoomManagerField = webViewClass.getDeclaredField("mZoomManager");
mZoomManagerField.setAccessible(true);
Object mZoomManagerInstance = mZoomManagerField.get(mWebview);
// modify the "default max zoom scale" value, which controls the upper limit
// and set it to something very large; e.g. Float.MAX_VALUE
Class<?> zoomManagerClass = Class.forName("android.webkit.ZoomManager");
Field mDefaultMaxZoomScaleField = zoomManagerClass.getDeclaredField("mDefaultMaxZoomScale");
mDefaultMaxZoomScaleField.setAccessible(true);
mDefaultMaxZoomScaleField.set(mZoomManagerInstance, Float.MAX_VALUE);
I want to display two Unicode characters in TextView, but I get squares:
- ℏ (reduced Planck constant/PLANCK CONSTANT OVER TWO PI http://www.fileformat.info/info/unicode/char/210f/index.htm)
- ℞ (PRESCRIPTION TAKE http://www.fileformat.info/info/unicode/char/211e/index.htm)
I know that not all Unicode characters are supported by default Android font, but reduced "h-bar" is Latin character and it's one of the fundamental physical constants. Can anyone confirm that I making everything right? And if, how to solve this problem (third-part font is the only solution)?
view = new TextView(this);
int[] codePoint = { 0x210f, 0x211e };
String hhh = new String(codePoint, 0, codePoint.length);
view.setText(hhh);
According to the character set page the Droid fonts don't support U+210F (ℏ), but they do support U+0127 (ħ), so you might consider using an italic font and U+0127 instead.
add font containing characters to /system/fonts,
modify /system/etc/fallback_fonts.xml so android finds font then
reboot.
Everything should be working now