MISE À JOUR: résolu! Le problème était lié à mon Viewpager et non à WebView.
J'essaie d'ajouter une fonction "Retour" à ma WebView
qui se trouve dans une Fragment
. Mais je n'arrive pas à comprendre comment:
public final class TestFragment extends Fragment {
static WebView mWeb;
private View mContentView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
mContentView = inflater.inflate(R.layout.webview, null);
mWeb = (WebView)mContentView.findViewById(R.id.webview);
WebSettings settings = mWeb.getSettings();
settings.setJavaScriptEnabled(true);
settings.setSupportZoom(false);
mWeb.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
mWeb.getSettings().setBuiltInZoomControls(false);
mWeb.loadUrl("myurl...");
mWeb.setOnKeyListener(new OnKeyListener(){
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWeb.canGoBack()) {
mWeb.goBack();
return true;
}
return false;
}
});
}
}
J'ai aussi essayé quelque chose comme:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWeb.canGoBack()) {
mWeb.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
Une autre solution mais le même problème:
@Override
public void onBackPressed()
{
if(webView.canGoBack())
webView.goBack();
else
super.onBackPressed();
}
Des idées comment faire fonctionner cela?
Peut-être sa restriction Android. Essayez de faire cela en utilisant handler.
public final class TestFragment extends Fragment {
static WebView mWeb;
private View mContentView;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message message) {
switch (message.what) {
case 1:{
webViewGoBack();
}break;
}
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
mContentView = inflater.inflate(R.layout.webview, null);
mWeb = (WebView)mContentView.findViewById(R.id.webview);
WebSettings settings = mWeb.getSettings();
settings.setJavaScriptEnabled(true);
settings.setSupportZoom(false);
mWeb.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
mWeb.getSettings().setBuiltInZoomControls(false);
mWeb.loadUrl("myurl...");
mWeb.setOnKeyListener(new OnKeyListener(){
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.getAction() == MotionEvent.ACTION_UP
&& mWeb.canGoBack()) {
handler.sendEmptyMessage(1);
return true;
}
return false;
}
});
}
private void webViewGoBack(){
mWeb.goBack();
}
}
En fait, vous ne pouvez pas faire directement à l'intérieur du fragment. La onBackPressed
peut être remplacée dans la FragmentActivity
. Ce que vous pouvez faire c'est:
onBackPressed
dans l'activité.onBackPressed
est appelée, vérifiez si l'instance du fragment actuel est l'instance affichant la variable webview
.fragment
si la webview
peut remonter. super
ou ce dont vous avez besoinModifier:
@Override
public void onBackPressed() {
Fragment webview = getSupportFragmentManager().findFragmentByTag("webview");
if (webview instanceof MyWebViewFragment) {
boolean goback = ((MyWebViewFragment)webview).canGoBack();
if (!goback)
super.onBackPressed();
}
}
Vous pouvez vérifier ce code:
webView.canGoBack();
webView.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.getAction() == MotionEvent.ACTION_UP
&& webView.canGoBack()) {
webView.goBack();
return true;
}
return false;
}
});
Dans WebViewActivity.Java
, j'ai ajouté 1 méthode:
@Override
public void onBackPressed() {
WebViewFragment fragment = (WebViewFragment)
getSupportFragmentManager().findFragmentById(R.id.fragmentContainer);
if (fragment.canGoBack()) {
fragment.goBack();
} else {
super.onBackPressed();
}
}
Dans WebViewFragment.Java
, j'ai ajouté 2 méthodes:
public boolean canGoBack() {
return mWebView.canGoBack();
}
public void goBack() {
mWebView.goBack();
}
ma solution était dans le fragment que j'ai ajouté aux méthodes publiques
public static boolean canGoBack(){
return mWebView.canGoBack();
}
public static void goBack(){
mWebView.goBack();
}
puis de l'activité que j'appelle
@Override
public void onBackPressed() {
if(webFragment.canGoBack()){
webFragment.goBack();
}else{
super.onBackPressed();
}
}
note la mwebview est statique
vous pouvez le faire en:
dans la Activity
put:
// Set WebView
public void setWebView(WebView web) {
this.web = web;
}
dans le fragment Web après ActivityCreated()
put:
((Your_Activity) getActivity()).setWebView(webView);
N'oubliez pas de définir webView
de la onCreateView()
comme ceci:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
webView = (WebView) inflater.inflate(R.layout.your_web_fragment, container,
false);
return web;
}
La réponse de @ RomanBlack m'a donné la bonne idée, mais puisque nous utilisons kotlin, j'ai dû adapter un peu la réponse.
webView.setOnKeyListener { _, _, keyEvent ->
if (keyEvent.keyCode == KeyEvent.KEYCODE_BACK && !webView.canGoBack()) {
false
} else if (keyEvent.keyCode == KeyEvent.KEYCODE_BACK && keyEvent.action == MotionEvent.ACTION_UP) {
webView.goBack()
true
} else true
}
si vous voulez le faire avec des déclarations, vous devez ajouter quelque chose comme:
return@setOnKeyListener true
@OmidAmnivia answer est correcte, votre application la solution au crash
@Override
public void onBackPressed() {
if(webFragment.isInitialized && webFragment.canGoBack()){
webFragment.goBack();
}else{
super.onBackPressed();
}
}
Vous devez vérifier si votre classe a été initialisée ou non.
J'ai créé une interface simple:
public interface IOnBackPressed {
boolean onBackPressed();
}
dans l'activité:
public class MyActivity extends Activity {
@Override public void onBackPressed() {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_container);
if (!(fragment instanceof IOnBackPressed) || !((IOnBackPressed) fragment).onBackPressed()) {
super.onBackPressed();
}
}
}
dans le fragment:
public class MyFragment extends Fragment implements IOnBackPressed {
@Override
public boolean onBackPressed() {
if (webview.canGoBack()) {
webview.goBack();
// backpress is not considered in the Activity
return true;
} else {
// activity will act normal
return false;
}
}
}
Tout d'abord, retourne pressé dans le fragment
mContentView.setFocusableInTouchMode(true);
mContentView.requestFocus();
mContentView.setOnKeyListener( new OnKeyListener()
{
@Override
public boolean onKey( View v, int keyCode, KeyEvent event )
{
if( keyCode == KeyEvent.KEYCODE_BACK )
{
if (mWebView.canGoBack()) {
mWebView.goBack();
retune false;
} else {
return true;
}
}
return false;
}
} );
j'espère que ça va marcher.
Voici comment je l'ai fait dans mon application. Je consomme des événements de presse jusqu'à ce que la vue Web puisse revenir. Une fois que l'affichage Web ne peut plus revenir en arrière, je montre à l'utilisateur que s'il continue d'appuyer en arrière, l'application se ferme.
Il donnera à l'utilisateur une chance de rester dans votre application lorsque la visualisation Web ne peut pas revenir en arrière. Je le sentais plus convivial:
//time passed between two back presses.
private val TIME_INTERVAL = 200
// variable to keep track of last back press
private var mBackPressed: Long = 0
webView!!.requestFocus()
webView.setOnKeyListener(View.OnKeyListener { v, keyCode, event ->
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.action == MotionEvent.ACTION_UP
) {
if(webView.canGoBack()) {
//go back in previous page
webView.goBack()
return@OnKeyListener true
}
else
{
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
{ // dont consume back press and pass to super
return@OnKeyListener false
}
else {
// show hint for double back press
Toast.makeText(context, " Double Tap back button to exit the demo", Toast.LENGTH_SHORT).show();
mBackPressed = System.currentTimeMillis();
return@OnKeyListener true
}
}
}
return@OnKeyListener false
})