带有书签的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"。

