Sure, here’s the translation: Android Tabview + Webview

huangapple go评论89阅读模式
英文:

Android Tabview + Webview

问题

我想在选项卡更改时使 WebView 内容改变(URL 更改)。然而,我的代码有问题。当我切换选项卡时,它显示上一个选项卡的内容。

例如,
应用初始化 -> 显示第一个选项卡和第一个选项卡的 WebView 内容(成功)
点击选项卡2 -> 显示第二个选项卡,但显示第一个选项卡的 WebView 内容(失败)
点击选项卡3 -> 显示第三个选项卡,但显示第一个选项卡的 WebView 内容(失败)
返回选项卡2 -> 显示第二个选项卡和第二个选项卡的 WebView 内容(成功)

请帮助。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
        final ViewPager viewPager = findViewById(R.id.view_pager);
        viewPager.setAdapter(sectionsPagerAdapter);
        TabLayout tabs = findViewById(R.id.tabs);
        tabs.setupWithViewPager(viewPager);
        tabs.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
    }
}

SectionsPagerAdapter.java

public class SectionsPagerAdapter extends FragmentPagerAdapter {

    @StringRes
    private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2, R.string.tab_text_3, R.string.tab_text_4, R.string.tab_text_5, R.string.tab_text_6, R.string.tab_text_7};
    private final Context mContext;

    public SectionsPagerAdapter(Context context, FragmentManager fm) {
        super(fm);
        mContext = context;
    }

    @Override
    public Fragment getItem(int position) {
        return PlaceholderFragment.newInstance(position + 1);
    }

    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        return mContext.getResources().getString(TAB_TITLES[position]);
    }

    @Override
    public int getCount() {
        return 7;
    }
}

PlaceholderFragment.java

public class PlaceholderFragment extends Fragment {

    String type;

    private static final String ARG_SECTION_NUMBER = "section_number";

    private PageViewModel pageViewModel;

    public static PlaceholderFragment newInstance(int index) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle bundle = new Bundle();
        bundle.putInt(ARG_SECTION_NUMBER, index);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        pageViewModel = ViewModelProviders.of(this).get(PageViewModel.class);
        int index = 1;
        if (getArguments() != null) {
            index = getArguments().getInt(ARG_SECTION_NUMBER);
        }
        pageViewModel.setIndex(index);
    }

    @Override
    public View onCreateView(
            @NonNull LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_main, container, false);
        final WebView webView = (WebView)root.findViewById(R.id.webView);
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                webView.loadUrl(url);
                return true;
            }
        });
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);

        pageViewModel.getText().observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable String s) {
                type = s;
            }
        });

        if (type == null) {
            type = "1";
        }

        webView.loadUrl("https://my.domain/list.php?type=" + type);
        return root;
    }
}

PageViewModel.java

public class PageViewModel extends ViewModel {

    private MutableLiveData<Integer> mIndex = new MutableLiveData<>();
    private LiveData<String> mText = Transformations.map(mIndex, new Function<Integer, String>() {
        @Override
        public String apply(Integer input) {
            return input.toString();
        }
    });

    public void setIndex(int index) {
        mIndex.setValue(index);
    }

    public LiveData<String> getText() {
        return mText;
    }
}
英文:

I want to make the webview content change (url change) when tab is changed.
However, my code is late. When I change tabs, it shows the last tab's content.

For example,<br/>
App Initialize -> shows first tab and first tab's webview (success)<br/>
Click Tab 2 -> shows second tab but first tab's webview (fail)<br/>
Click Tab 3 -> shows third tab but first tab's webview (fail)<br/>
Return to Tab 2 -> shows second tab and second tab's webview (success)<br/>

Please help.

MainActivity.java

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
final ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
tabs.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
}

SectionsPagerAdapter.java

/**
* A [FragmentPagerAdapter] that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
@StringRes
private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2, R.string.tab_text_3, R.string.tab_text_4, R.string.tab_text_5, R.string.tab_text_6, R.string.tab_text_7};
private final Context mContext;
public SectionsPagerAdapter(Context context, FragmentManager fm) {
super(fm);
mContext = context;
}
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1);
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return mContext.getResources().getString(TAB_TITLES[position]);
}
@Override
public int getCount() {
// Show 2 total pages.
return 7;
}
}

PlaceholderFragment.java

/**
* A placeholder fragment containing a simple view.
*/
public class PlaceholderFragment extends Fragment {
String type;
private static final String ARG_SECTION_NUMBER = &quot;section_number&quot;;
private PageViewModel pageViewModel;
public static PlaceholderFragment newInstance(int index) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle bundle = new Bundle();
bundle.putInt(ARG_SECTION_NUMBER, index);
fragment.setArguments(bundle);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pageViewModel = ViewModelProviders.of(this).get(PageViewModel.class);
int index = 1;
if (getArguments() != null) {
index = getArguments().getInt(ARG_SECTION_NUMBER);
}
pageViewModel.setIndex(index);
}
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_main, container, false);
final WebView webView = (WebView)root.findViewById(R.id.webView);
webView.setWebViewClient( new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url){
webView.loadUrl(url);
return true;
}
});
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
pageViewModel.getText().observe(this, new Observer&lt;String&gt;() {
@Override
public void onChanged(@Nullable String s) {
type = s;
}
});
if(type == null)
{
type=&quot;1&quot;;
}
webView.loadUrl(&quot;https://my.domain/list.php?type=&quot;+type);
return root;
}
}

PageViewModel.java

public class PageViewModel extends ViewModel {
private MutableLiveData&lt;Integer&gt; mIndex = new MutableLiveData&lt;&gt;();
private LiveData&lt;String&gt; mText = Transformations.map(mIndex, new Function&lt;Integer, String&gt;() {
@Override
public String apply(Integer input) {
return input.toString();
}
});
public void setIndex(int index) {
mIndex.setValue(index);
}
public LiveData&lt;String&gt; getText() {
return mText;
}
}

答案1

得分: 3

你可以在各个选项卡中添加一个加载器,直到 Web 视图加载完成。onPageFinished() 是在 Web 视图加载完成时的回调函数。

web_view.webViewClient = object : WebViewClient() {

    override fun onPageFinished(view: WebView, weburl: String) {
           // 停止加载
     }
}
英文:

You can add a loader till the webview loads in respective tabs. onPageFinished() is a callback when webview has completed loading

web_view.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, weburl: String) {
// Stop loading
}
}
</details>
# 答案2
**得分**: 0
我的建议是你应该将以下代码更改:
```lang-java
webView.loadUrl("https://my.domain/list.php?type=" + getArguments().getInt(ARG_SECTION_NUMBER));

并观察它的工作情况。如果它按照你的预期工作,我认为你可能根本不需要 PageViewModel.java

异常行为的根本原因

PageViewModel 中,mIndex 的值通过 PlaceholderFragmentonCreate 中的以下行进行更新:

pageViewModel.setIndex(index);

它还改变了 mText 的值,而这个值在 PlaceholderFragment 中的 onCreateView 中的以下块中被观察:

pageViewModel.getText().observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
type = s;
}
});

因此,PageViewModelPlaceholderFragment 出现了意外的竞争。

ViewPager 在早期创建了更多的 Fragment,正如 setOffscreenPageLimit 中所写。在 PlaceholderFragmentonCreate 中更新 mIndex 的值不是一个好主意。

英文:

My recommendation is that you should change

webView.loadUrl(&quot;https://my.domain/list.php?type=&quot;+type);

to

webView.loadUrl(&quot;https://my.domain/list.php?type=&quot; + getArguments().getInt(ARG_SECTION_NUMBER));

and see how it works. If it works as you expected, I think you don't need the PageViewModel.java at all.

The root cause of unexpected behavior

In PageViewModel, the value of mIndex is updated by the following line of onCreate in PlaceholderFragment

pageViewModel.setIndex(index);

It also changes the value of mText, which is observed by the following block of onCreateView in PlaceholderFragment:

pageViewModel.getText().observe(this, new Observer&lt;String&gt;() {
@Override
public void onChanged(@Nullable String s) {
type = s;
}
});

Therefore, PageViewModel and PlaceholderFragment are in a race unexpectedly.

ViewPager creates more Fragment early, as written in setOffscreenPageLimit. It is not a good idea to update the value of mIndex in onCreate of PlaceholderFragment.

huangapple
  • 本文由 发表于 2020年8月30日 11:16:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/63653629.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定