Jongho
Jongho

Reputation: 1

Android Tabview + Webview

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,
App Initialize -> shows first tab and first tab's webview (success)
Click Tab 2 -> shows second tab but first tab's webview (fail)
Click Tab 3 -> shows third tab but first tab's webview (fail)
Return to Tab 2 -> shows second tab and second tab's webview (success)

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 = "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;
    }
}

Upvotes: 0

Views: 215

Answers (2)

qtmfld
qtmfld

Reputation: 3187

My recommendation is that you should change

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

to

webView.loadUrl("https://my.domain/list.php?type=" + 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<String>() {
            @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.

Upvotes: 0

Maithili Joshi
Maithili Joshi

Reputation: 134

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
     }
}

Upvotes: 3

Related Questions