在RecyclerView中加载WebViews时显示进度

时间:2018-04-01 02:49:50

标签: java android android-layout android-webview android-view

在我的Android活动中,我使用的RecyclerView包含MathViews个数字。 MathView是显示LaTeX内容的第三方库(This 有点类似WebView。在这个android项目中可以看到MathView的实现。 github.com/lingarajsankaravelu/Katex)。

问题是,为了呈现此MathView的内容,需要更长的时间。由于我在MathView中使用了少量RecycleView个组件,因此渲染时间会增加更多。因此,当Activity开始时,首先在视图中显示一些空白区域几秒钟,然后呈现相关内容。

作为此问题的解决方案,我需要显示一个进度条,直到完全呈现Activity的所有布局内容,并在渲染完成后显示Activity。

相关源代码如下所示。

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();
    }
}

最后实施。

RecyclerView recyclerView;
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);

        recyclerView.setHasFixedSize(true);
        recyclerView.setAdapter(new RecyclerAdapterEquations(sample));

3 个答案:

答案 0 :(得分:5)

借助azizbekian所写的答案,我找到了问题的答案。

answer所述,这是程序;

  
      
  1. 在xml文件中引入ProgressBar或类似内容。此视图应在RecyclerView之后声明   在RecyclerView
  2. 之上绘制   
  3. RecyclerView隐身(通过android:visibility="invisible"
  4.   
  5. 现在RecyclerView实际上已经布置未在屏幕上显示。你需要一个回调,这将被执行一段时间   稍后设置RecyclerView时。在你的回调中   将隐藏进度条并将RecyclerView的可见性更改为   View.VISIBLE
  6.   

现在由于katex.hourglass.in.mathlib.MathView是android WebView的子类,我们可以为此设置WebChromeClient。然后,我们可以获得加载内容的进度百分比。

 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();
         }
     }
 });

我们可以实施进度条来显示loadedPercentage。当loadedPercentage为100时,我们可以看到相关内容已完全加载。 所以我编辑了MathView类如下;

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() {
        //...
    }

}

答案 1 :(得分:3)

我无法在说明中看到问题本身,因此我将参考your statement in comments section

  

我只需要一个解决方案来显示进度条,直到Activity的所有布局内容完全呈现,然后在渲染完成后,显示Activity

  1. 在xml文件中引入ProgressBar或类似内容。应在RecyclerView之后声明此视图,以便在RecyclerView
  2. 之上绘制
  3. RecyclerView隐身(通过android:visibility="invisible"
  4. 现在RecyclerView实际上已经布置未在屏幕上显示。您需要一个回调,该回调将在稍后设置RecyclerView时执行。在此回调中,您将隐藏进度条并将RecyclerView的可见性更改为View.VISIBLE
  5. 问题在于附加&#34; RecyclerView的孩子已初始化&#34; 听众。

    只要katex.hourglass.in.mathlib.MathViewandroid.webkit.WebView的子类,这意味着,为了获得有关加载完成事件的通知,您应该按以下方法注册WebViewClient

    
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            Equation sampleEquation = equations.get(position);
            holder.mathView.setDisplayText(sampleEquation.equationString);
            holder.mathView.setWebViewClient(new WebViewClient() {
                public void onPageFinished(WebView view, String url) {
                    // No longer interested in upcoming events - unregister
                    view.setWebViewClient(null);
                    // Now data is loaded, can make RecyclerView visible
                }
            });
            ...
        }
    
    

    请注意,只要加载了RecyclerView,就会显示MathView。您可以根据需要等待所有这些加载。

答案 2 :(得分:0)

不要打电话

console.log(`User created ${user}`);
像往常一样,首先在适配器中加载数据,然后调用

setContentView(layout);

之后将适配器设置为recyclerview。