In my android activity I am using a RecyclerView
which contains number of MathViews
. MathView
is a third-party library which shows LaTeX contents (This
is somewhat similar to WebView
. Implementation of MathView
can be seen on this android project. github.com/lingarajsankaravelu/Katex).
The problem is, for rendering the content of this MathView
, it takes a little bit longer time. As I have used few MathView
components inside a RecycleView
and the rendering time increases more. Therefore when the Activity started, at first in the view, some white space are shown for few seconds and then the relevant content is rendered.
As a solution for this problem, I need to show a progress bar until all the layout content of the Activity is completely rendered and after rendering is completed show up the Activity.
The relavent source codes are shown below.
MathView;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:auto="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:id="@+id/equation_item"
android:clickable="true"
android:foreground="?attr/selectableItemBackground">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp">
<katex.hourglass.in.mathlib.MathView
android:id="@+id/math_view"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="left"
app:setClickable="true"
app:setTextColor="@color/colorPrimary"
app:setTextSize="10sp"
/>
</android.support.v7.widget.CardView>
<include layout="@layout/item_divider"/>
</LinearLayout>
Recycler View;
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.a37moons.mathcheatsheets.ContentActivity"
tools:showIn="@layout/activity_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view_equations"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.NestedScrollView>
ViewHolder Class
public class ViewHolder extends RecyclerView.ViewHolder {
public MathView mathView;
public ViewHolder(View itemView) {
super(itemView);
mathView = itemView.findViewById(R.id.math_view);
}
}
Recycler Adapter Class
public class RecyclerAdapterEquations extends RecyclerView.Adapter<ViewHolder>{
private List<Equation> equations;
View view;
public RecyclerAdapterEquations(List<Equation> equations){
this.equations = equations;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.equation_view_item,parent,false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Equation sampleEquation = equations.get(position);
holder.mathView.setDisplayText(sampleEquation.equationString);
// holder.mathView2.setText(sampleEquation.equationString);
Log.d("MATH_APP","position "+position+" mathview text set ");
}
@Override
public int getItemCount() {
return equations.size();
}
}
Finally the implementation.
RecyclerView recyclerView;
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(new RecyclerAdapterEquations(sample));
With the help of the answer of written by azizbekian, I found the answer to my question.
As mentioned in that answer, this is the procedure;
- Introduce a
ProgressBar
or something similar inside xml file. This view should be declared afterRecyclerView
in order to be drawn on top ofRecyclerView
- Make
RecyclerView
invisible (viaandroid:visibility="invisible"
)- Now
RecyclerView
will be actually laid out but not shown on the screen. You need a callback, that would be executed some time later whenRecyclerView
is already setup. Within this callback you will hide progress bar and change visibility ofRecyclerView
toView.VISIBLE
.
Now as the katex.hourglass.in.mathlib.MathView
is a subclass of android WebView
, we can set a WebChromeClient
to this. Then, we can get the percentage of progress of loading the content.
int loadedPercentage = 0;
boolean loaded = false;
mathView.setWebChromeClient(new WebChromeClient(){
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
loadedPercentage = newProgress;
if(newProgress==100) {
//When the loading is 100% completed; todo
loaded = true;
Toast.makeText(getContext(), newProgress + "LOADED COMPLETELY", Toast.LENGTH_SHORT).show();
}
}
});
We can implement a progress bar to show the loadedPercentage
. When the loadedPercentage
is 100, we can see the relavent content is completely loaded.
So I editted the MathView
class as follows;
public class MyMathView extends WebView {
private String TAG = "KhanAcademyKatexView";
private static final float default_text_size = 18;
private String display_text;
private int text_color;
private int text_size;
private boolean clickable = false;
private boolean loaded = false;
private int loadedPercentage = 0;
public MyMathView(Context context) {
//...
}
public MyMathView(Context context, AttributeSet attrs) {
//...
}
public boolean isLoaded(){
return loaded;
}
public int getLoadedPercentage() {
return loadedPercentage;
}
public void setViewBackgroundColor(int color)
{
//...
}
private void pixelSizeConversion(float dimension) {
//...
}
private void configurationSettingWebView()
{
//...
}
public void setDisplayText(String formula_text) {
this.display_text = formula_text;
loadData();
}
private String getOfflineKatexConfig()
{
String offline_config = "<!DOCTYPE html>\n" +
"<html>\n" +
" <head>\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>Auto-render test</title>\n" +
" <link rel=\"stylesheet\" type=\"text/css\" href=\"file:///android_asset/katex/katex.min.css\">\n" +
" <link rel=\"stylesheet\" type=\"text/css\" href=\"file:///android_asset/themes/style.css\">\n" +
" <script type=\"text/javascript\" src=\"file:///android_asset/katex/katex.min.js\"></script>\n" +
" <script type=\"text/javascript\" src=\"file:///android_asset/katex/contrib/auto-render.min.js\"></script>\n" +
" <style type='text/css'>"+
"body {"+
"margin: 0px;"+
"padding: 0px;"+
"font-size:" +this.text_size+"px;"+
"color:"+getHexColor(this.text_color)+";"+
" }"+
" </style>"+
" </head>\n" +
" <body>\n" +
" {formula}\n" +
" <script>\n" +
" renderMathInElement(\n" +
" document.body\n" +
" );\n" +
" </script>\n" +
" </body>\n" +
"</html>";
String start = "<html><head><meta http-equiv='Content-Type' content='text/html' charset='UTF-8' /><style> body {"+
" white-space: nowrap;}</style></head><body>";
String end = "</body></html>";
//return start+offline_config.replace("{formula}",this.display_text)+end;
return offline_config.replace("{formula}",this.display_text);
}
private void loadData()
{
if (this.display_text!=null)
{
loadedPercentage = 0;
loaded = false;
this.setWebChromeClient(new WebChromeClient(){
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
loadedPercentage = newProgress;
if(newProgress==100) {
loaded = true;
Toast.makeText(getContext(), newProgress + "LOADED", Toast.LENGTH_SHORT).show();
}
}
});
this.loadDataWithBaseURL("null",getOfflineKatexConfig(),"text/html","UTF-8","about:blank");
}
}
public void setTextSize(int size)
{
//...
}
public void setTextColor(int color)
{
//...
}
private String getHexColor(int intColor)
{
//...
}
private void setDefaultTextColor(Context context) {
//...
}
private void setDefaultTextSize() {
//...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With