带有书签的Android WebView
为了将网页显示为应用程序的一部分,我们在应用程序中使用android WebView。
我们在这里介绍了WebView的基础知识。
在本教程中,我们将使用WebView实现加载进度条,并允许为URL加书签以便以后查看。
让我们开始吧。
Android WebView
AndroidWebView
类是Android View类的扩展,它允许您将网页显示为活动布局的一部分。
要加载外部页面,我们在WebView实例上调用方法loadUrl(String url),并传入外部页面的url。
WebViewClient包含以下四个通常被覆盖的重要方法。
onPageStarted
:顾名思义,该方法在开始加载URL时被调用。shouldOverrideUrlLoading
:每当单击来自已加载页面的内部链接时,都会调用此方法。
对于API> 24,不建议使用" shouldOverrideUrlLoading(WebView视图,字符串url)",而应使用" shouldOverrideUrlLoading(WebView视图,WebResourceRequest请求)"。onPageFinished
:完全成功加载url时,将调用它onReceivedError
:未加载网址时,将调用此方法。
为了在webview上启用缩放控件,我们可以在webView实例上调用以下方法。
webView.getSettings().setSupportZoom(true); webView.getSettings().setBuiltInZoomControls(true); //allow pinch to zooom webView.getSettings().setDisplayZoomControls(false); //disable the default zoom controls on the page
让我们创建一个在显示ProgressBar的同时加载网页的应用程序。
我们将添加一项功能,使我们可以为URL添加书签并将其保存在SharedPreferences中,以供以后查看。
具有书签项目结构的Android WebView
我们已将"活动"类型选择为"导航抽屉"。
注意:如果您已将构建工具更新为API 26,并且遇到错误:"无法解决com.android.support:appcompat-v7:26.0.1",则需要在build.gradle
文件,如下所示:
apply plugin: 'com.android.application' allprojects { repositories { jcenter() maven { url "https://maven.google.com" } } } android { compileSdkVersion 26 buildToolsVersion "26.0.1" defaultConfig { applicationId "com.theitroad.webviewwithbookmarks" minSdkVersion 16 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:26.0.1' compile 'com.android.support:design:26.0.1' compile 'com.google.code.gson:gson:2.7' compile 'com.android.support.constraint:constraint-layout:1.0.2' testCompile 'junit:junit:4.12' }
注意:上面还添加了用于在"共享首选项"中保存书签网址的Gson库依赖项。
Android WebView书签代码
" activity_main.xml"布局的代码如下:
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start"> <include layout="@layout/app_bar_main" android:layout_width="match_parent" android:layout_height="match_parent" <android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header_main" app:menu="@menu/activity_main_drawer" </android.support.v4.widget.DrawerLayout>
下面给出了app_bar_main.xml布局的代码:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.theitroad.webviewwithbookmarks.MainActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main" </android.support.design.widget.CoordinatorLayout>
下面给出了content_main.xml的布局。
它包含一个用于启动其他活动的按钮。
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://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.theitroad.webviewwithbookmarks.MainActivity" tools:showIn="@layout/app_bar_main"> <Button android:id="@+id/btnLaunchWebsite" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="LAUNCH WEBSITE" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" </android.support.constraint.ConstraintLayout>
MainActivity.java的代码如下:
package com.theitroad.webviewwithbookmarks; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.support.design.widget.NavigationView; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.widget.Button; public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { Button button; NavigationView navigationView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); DrawerLayout drawer = findViewById(R.id.drawer_layout); button = findViewById(R.id.btnLaunchWebsite); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { gotoBrowserActivity(); } }); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.addDrawerListener(toggle); toggle.syncState(); navigationView = findViewById(R.id.nav_view); navigationView.setNavigationItemSelectedListener(this); } @Override public void onBackPressed() { DrawerLayout drawer = findViewById(R.id.drawer_layout); if (drawer.isDrawerOpen(GravityCompat.START)) { drawer.closeDrawer(GravityCompat.START); } else { super.onBackPressed(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { //Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { //Handle action bar item clicks here. The action bar will //automatically handle clicks on the Home/Up button, so long //as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @Override public boolean onNavigationItemSelected(MenuItem item) { //Handle navigation view item clicks here. int id = item.getItemId(); if (id == R.id.nav_home) { navigationView.getMenu().getItem(0).setChecked(false); } else if (id == R.id.nav_bookmark) { navigationView.getMenu().getItem(1).setChecked(false); startActivity(new Intent(this, BookmarkActivity.class)); } DrawerLayout drawer = findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; } private void gotoBrowserActivity() { startActivity(new Intent(this, BrowserActivity.class)); } }
在上面的代码中,我们在NavigationDrawer中定义了两个菜单选项(文件位于菜单文件夹中,名称为" activity_main_drawer.xml")。
单击MainActivity.java中的按钮将启动BrowserActivity.java,然后单击Bookmark菜单按钮将启动BookmarkActivity.java,我们将很快看到。
在您的AndroidManifest.xml中添加以下访问互联网的权限。
<uses-permission android:name="android.permission.INTERNET"
下面给出了" activity_browser.xml"的代码。
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" android:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fadeScrollbars="false" android:scrollbarFadeDuration="0" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="wrap_content" </android.support.v4.widget.NestedScrollView> <ProgressBar android:id="@+id/progressBar" style="@style/Widget.AppCompat.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="-7dp" android:indeterminate="true" android:visibility="gone" app:layout_behavior="@string/appbar_scrolling_view_behavior" </android.support.design.widget.CoordinatorLayout>
下面给出了" BrowserActivity.java"的代码:
package com.theitroad.webviewwithbookmarks; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.os.Bundle; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.webkit.WebResourceError; import android.webkit.WebResourceRequest; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ProgressBar; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.util.ArrayList; public class BrowserActivity extends AppCompatActivity { public static final String PREFERENCES = "PREFERENCES_NAME"; public static final String WEB_LINKS = "links"; public static final String WEB_TITLE = "title"; WebView webView; private ProgressBar progressBar; String current_page_url = "https://www.wikipedia.com"; CoordinatorLayout coordinatorLayout; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_browser); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setTitle(""); toolbar.setNavigationIcon(R.drawable.ic_arrow_back); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); if (getIntent().getExtras() != null) { current_page_url = getIntent().getStringExtra("url"); } webView = findViewById(R.id.webView); progressBar = findViewById(R.id.progressBar); webView.loadUrl(current_page_url); initWebView(); coordinatorLayout = findViewById(R.id.main_content); } private void initWebView() { webView.setWebViewClient(new WebViewClient() { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); progressBar.setVisibility(View.VISIBLE); current_page_url = url; invalidateOptionsMenu(); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { webView.loadUrl(url); return true; } @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { webView.loadUrl(request.getUrl().toString()); } return true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); progressBar.setVisibility(View.GONE); invalidateOptionsMenu(); } @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { super.onReceivedError(view, request, error); progressBar.setVisibility(View.GONE); invalidateOptionsMenu(); } }); webView.getSettings().setLoadWithOverviewMode(true); webView.getSettings().setUseWideViewPort(true); webView.clearCache(true); webView.clearHistory(); webView.getSettings().setJavaScriptEnabled(true); webView.setHorizontalScrollBarEnabled(true); } @Override public boolean onCreateOptionsMenu(Menu menu) { //Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.browser, menu); SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE); String links = sharedPreferences.getString(WEB_LINKS, null); if (links != null) { Gson gson = new Gson(); ArrayList<String> linkList = gson.fromJson(links, new TypeToken<ArrayList<String>>() { }.getType()); if (linkList.contains(current_page_url)) { menu.getItem(0).setIcon(R.drawable.ic_bookmark_black_24dp); } else { menu.getItem(0).setIcon(R.drawable.ic_bookmark_border_black_24dp); } } else { menu.getItem(0).setIcon(R.drawable.ic_bookmark_border_black_24dp); } return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_bookmark) { String message; SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE); String jsonLink = sharedPreferences.getString(WEB_LINKS, null); String jsonTitle = sharedPreferences.getString(WEB_TITLE, null); if (jsonLink != null && jsonTitle != null) { Gson gson = new Gson(); ArrayList<String> linkList = gson.fromJson(jsonLink, new TypeToken<ArrayList<String>>() { }.getType()); ArrayList<String> titleList = gson.fromJson(jsonTitle, new TypeToken<ArrayList<String>>() { }.getType()); if (linkList.contains(current_page_url)) { linkList.remove(current_page_url); titleList.remove(webView.getTitle().trim()); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(WEB_LINKS, new Gson().toJson(linkList)); editor.putString(WEB_TITLE, new Gson().toJson(titleList)); editor.apply(); message = "Bookmark Removed"; } else { linkList.add(current_page_url); titleList.add(webView.getTitle().trim()); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(WEB_LINKS, new Gson().toJson(linkList)); editor.putString(WEB_TITLE, new Gson().toJson(titleList)); editor.apply(); message = "Bookmarked"; } } else { ArrayList<String> linkList = new ArrayList<>(); ArrayList<String> titleList = new ArrayList<>(); linkList.add(current_page_url); titleList.add(webView.getTitle()); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(WEB_LINKS, new Gson().toJson(linkList)); editor.putString(WEB_TITLE, new Gson().toJson(titleList)); editor.apply(); message = "Bookmarked"; } Snackbar snackbar = Snackbar.make(coordinatorLayout, message, Snackbar.LENGTH_LONG); snackbar.show(); invalidateOptionsMenu(); } return super.onOptionsItemSelected(item); } @Override public void onBackPressed() { if (webView.canGoBack()) { webView.goBack(); } else { super.onBackPressed(); } } }
在上面的代码中,我们将URLhttps://www.wikipedia.com
加载到WebView中。
分别在加载和完成URL时显示和隐藏ProgressBar。
菜单从browser.xml
文件中被放大,如下所示。
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto"> <item android:id="@+id/action_bookmark" android:icon="@drawable/ic_bookmark_black_24dp" android:orderInCategory="100" android:title="BOOKMARK" app:showAsAction="always" </menu>
在" onCreateOptionsMenu()"中,我们检查current_page_url是否已存在于我们的SharedPreferences中。
根据结果,我们显示相关的书签菜单图标。
在onOptionsItemSelected()
中,我们根据是否存在URL存储或者从SharedPreferences中删除该URL。
SharedPreferences以Gson字符串的形式存储链接的ArrayList和相应的网页标题,这些字符串最终将显示在" BookmarkActivity.java"中,我们将在下面进行讨论。
invalidateOptionsMenu()用于重新绘制工具列中的菜单。
如果用户通过使用canGoBack()和goBack()检查并返回来单击WebView中的任何内部链接,则使用onBackPressed()来浏览网页。
下面给出了" activity_bookmark.xml"的代码。
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:layout_alignParentTop="true" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipeToRefresh" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/toolbar" android:layout_margin="@dimen/fab_margin"> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="wrap_content" </android.support.v4.widget.SwipeRefreshLayout> <LinearLayout android:id="@+id/emptyList" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" android:orientation="vertical" android:visibility="gone"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:text="WHOOPS" android:textColor="#212121" android:textSize="20sp" android:textStyle="bold" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:text="There are no bookmarks at the moment" android:textColor="#212121" </LinearLayout> </RelativeLayout>
下面给出了BookmarkActivity.java的代码。
package com.theitroad.webviewwithbookmarks; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.AdapterView; import android.widget.LinearLayout; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.SimpleAdapter; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import static com.theitroad.webviewwithbookmarks.BrowserActivity.PREFERENCES; import static com.theitroad.webviewwithbookmarks.BrowserActivity.WEB_LINKS; import static com.theitroad.webviewwithbookmarks.BrowserActivity.WEB_TITLE; public class BookmarkActivity extends AppCompatActivity { ArrayList<HashMap<String, String>> listRowData; public static String TAG_TITLE = "title"; public static String TAG_LINK = "link"; ListView listView; ListAdapter adapter; LinearLayout linearLayout; SwipeRefreshLayout mSwipeRefreshLayout; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bookmark); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setTitle("BOOKMARKS"); toolbar.setNavigationIcon(R.drawable.ic_arrow_back); toolbar.setTitleTextColor(getResources().getColor(android.R.color.white)); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); listView = findViewById(R.id.listView); linearLayout = findViewById(R.id.emptyList); mSwipeRefreshLayout = findViewById(R.id.swipeToRefresh); mSwipeRefreshLayout.setColorSchemeResources(R.color.colorAccent); mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { new LoadBookmarks().execute(); } }); new LoadBookmarks().execute(); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Object o = listView.getAdapter().getItem(position); if (o instanceof Map) { Map map = (Map) o; Intent in = new Intent(BookmarkActivity.this, BrowserActivity.class); in.putExtra("url", String.valueOf(map.get(TAG_LINK))); startActivity(in); } } }); listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) { Object o = listView.getAdapter().getItem(i); if (o instanceof Map) { Map map = (Map) o; deleteBookmark(String.valueOf(map.get(TAG_TITLE)), String.valueOf(map.get(TAG_LINK))); } return true; } }); } private class LoadBookmarks extends AsyncTask<String, String, String> { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(String... args) { //updating UI from Background Thread runOnUiThread(new Runnable() { public void run() { SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE); String jsonLink = sharedPreferences.getString(WEB_LINKS, null); String jsonTitle = sharedPreferences.getString(WEB_TITLE, null); listRowData = new ArrayList<>(); if (jsonLink != null && jsonTitle != null) { Gson gson = new Gson(); ArrayList<String> linkArray = gson.fromJson(jsonLink, new TypeToken<ArrayList<String>>() { }.getType()); ArrayList<String> titleArray = gson.fromJson(jsonTitle, new TypeToken<ArrayList<String>>() { }.getType()); for (int i = 0; i < linkArray.size(); i++) { HashMap<String, String> map = new HashMap<>(); if (titleArray.get(i).length() == 0) map.put(TAG_TITLE, "Bookmark " + (i + 1)); else map.put(TAG_TITLE, titleArray.get(i)); map.put(TAG_LINK, linkArray.get(i)); listRowData.add(map); } adapter = new SimpleAdapter(BookmarkActivity.this, listRowData, R.layout.bookmark_list_row, new String[]{TAG_TITLE, TAG_LINK}, new int[]{R.id.title, R.id.link}); listView.setAdapter(adapter); } linearLayout.setVisibility(View.VISIBLE); listView.setEmptyView(linearLayout); } }); return null; } protected void onPostExecute(String args) { mSwipeRefreshLayout.setRefreshing(false); } } private void deleteBookmark(final String title, final String link) { new AlertDialog.Builder(this) .setTitle("DELETE") .setMessage("Confirm that you want to delete this bookmark?") .setPositiveButton("YES", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE); String jsonLink = sharedPreferences.getString(WEB_LINKS, null); String jsonTitle = sharedPreferences.getString(WEB_TITLE, null); if (jsonLink != null && jsonTitle != null) { Gson gson = new Gson(); ArrayList<String> linkArray = gson.fromJson(jsonLink, new TypeToken<ArrayList<String>>() { }.getType()); ArrayList<String> titleArray = gson.fromJson(jsonTitle, new TypeToken<ArrayList<String>>() { }.getType()); linkArray.remove(link); titleArray.remove(title); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(WEB_LINKS, new Gson().toJson(linkArray)); editor.putString(WEB_TITLE, new Gson().toJson(titleArray)); editor.apply(); new LoadBookmarks().execute(); } dialogInterface.dismiss(); } }).setNegativeButton("NO", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); } }).show(); } }
在上面的代码中,我们使用Gson反序列化了SharedPreferences
中的字符串,并将它们转换为AsyncTask LoadBookmarks内部的相应链接和标题ArrayList of Strings。
SimpleAdapter是ListView的内置适配器。
将静态数据映射到XML文件中定义的视图很有用。
ListView行的布局如下所示:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="1" android:paddingBottom="2dp" android:paddingTop="4dp" android:textColor="#000" android:textSize="16sp" <TextView android:id="@+id/link" android:layout_width="match_parent" android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="1" android:layout_below="@+id/title" android:paddingBottom="4dp" android:paddingTop="2dp" android:textSize="14sp" </RelativeLayout>
调用setOnItemLongClickListener()可以长按删除书签。
返回一个" false"也会同时调用" setOnItemClickListener()",因此建议返回" true"。