Brion VIBBER has submitted this change and it was merged.
Change subject: Implement a rough ToC
......................................................................
Implement a rough ToC
- Accessed from overflow menu
- Tap each section to go to it
- Only section levels 1 and 2 are shown
- Also adds fadeIn & fadeOut utility methods
Change-Id: I475fefb3d0652cf96b1246489935528c7736d1c6
---
M wikipedia/assets/main.js
M wikipedia/res/layout/fragment_page.xml
A wikipedia/res/layout/header_toc_list.xml
A wikipedia/res/layout/item_toc_entry.xml
M wikipedia/res/menu/menu_page_actions.xml
M wikipedia/res/values/strings.xml
M wikipedia/src/main/java/org/wikipedia/Utils.java
A wikipedia/src/main/java/org/wikipedia/events/ShowToCEvent.java
M wikipedia/src/main/java/org/wikipedia/page/PageActionsHandler.java
M wikipedia/src/main/java/org/wikipedia/page/PageActivity.java
M wikipedia/src/main/java/org/wikipedia/page/PageViewFragment.java
A wikipedia/src/main/java/org/wikipedia/page/ToCHandler.java
12 files changed, 252 insertions(+), 14 deletions(-)
Approvals:
Brion VIBBER: Verified; Looks good to me, approved
diff --git a/wikipedia/assets/main.js b/wikipedia/assets/main.js
index 208c530..c8b3ffd 100644
--- a/wikipedia/assets/main.js
+++ b/wikipedia/assets/main.js
@@ -11,6 +11,7 @@
var title = document.createElement( "h1" );
title.textContent = payload.title;
+ title.id = "heading_" + payload.section.id;
document.getElementById( "content" ).appendChild( title );
var content = document.createElement( "div" );
@@ -76,6 +77,13 @@
bridge.sendMessage( "imagesListResponse", { "images": imageURLs });
} );
+ bridge.registerListener( "scrollToSection", function ( payload ) {
+ // The 52 is for dealing with the search header
+ var scrollY = document.getElementById( "heading_" +
payload.sectionID).offsetTop - 52;
+ window.scrollTo(0, scrollY);
+ });
+
+
var actionHandlers = {
"edit_section": function( el, event ) {
bridge.sendMessage( 'editSectionClicked', { sectionID:
el.getAttribute( 'data-id' ) } );
diff --git a/wikipedia/res/layout/fragment_page.xml
b/wikipedia/res/layout/fragment_page.xml
index 6743479..1e9b487 100644
--- a/wikipedia/res/layout/fragment_page.xml
+++ b/wikipedia/res/layout/fragment_page.xml
@@ -17,6 +17,15 @@
android:layout_height="match_parent"
android:visibility="gone"
/>
+ <ListView
+ android:id="@+id/page_toc_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ android:background="@android:color/background_light"
+ android:divider="#ededed"
+ android:dividerHeight="0.5dp"
+ />
<LinearLayout
android:id="@+id/page_error"
android:layout_width="match_parent"
diff --git a/wikipedia/res/layout/header_toc_list.xml
b/wikipedia/res/layout/header_toc_list.xml
new file mode 100644
index 0000000..4ad6978
--- /dev/null
+++ b/wikipedia/res/layout/header_toc_list.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:fontFamily="serif"
+ android:padding="16dp"
+ android:textStyle="bold"
+ style="?android:textAppearanceLarge"
+ />
+
diff --git a/wikipedia/res/layout/item_toc_entry.xml
b/wikipedia/res/layout/item_toc_entry.xml
new file mode 100644
index 0000000..f18d9b6
--- /dev/null
+++ b/wikipedia/res/layout/item_toc_entry.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ >
+ <View android:layout_width="0dp" android:layout_height="match_parent"
+ android:id="@+id/page_toc_filler"
+ />
+
+ <TextView
+ android:id="@+id/page_toc_item_text"
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_gravity="center_vertical"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ style="?android:textAppearanceMedium"
+ />
+
+</LinearLayout>
diff --git a/wikipedia/res/menu/menu_page_actions.xml
b/wikipedia/res/menu/menu_page_actions.xml
index 7e31994..960f798 100644
--- a/wikipedia/res/menu/menu_page_actions.xml
+++ b/wikipedia/res/menu/menu_page_actions.xml
@@ -1,7 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
-
+ <item android:id="@+id/menu_show_toc"
+ android:title="@string/menu_show_toc"
+ android:enabled="false"
+ android:showAsAction="always"
+ />
<item android:id="@+id/menu_other_languages"
android:title="@string/menu_other_languages"
android:enabled="false"
diff --git a/wikipedia/res/values/strings.xml b/wikipedia/res/values/strings.xml
index 0978fd9..994991f 100644
--- a/wikipedia/res/values/strings.xml
+++ b/wikipedia/res/values/strings.xml
@@ -51,4 +51,5 @@
<string name="dialog_message_edit_failed">Edit failed!</string>
<string name="dialog_message_edit_failed_retry">Retry</string>
<string name="dialog_message_edit_failed_cancel">Cancel</string>
+ <string name="menu_show_toc">Table of Contents</string>
</resources>
\ No newline at end of file
diff --git a/wikipedia/src/main/java/org/wikipedia/Utils.java
b/wikipedia/src/main/java/org/wikipedia/Utils.java
index cf5f1f0..39fba22 100644
--- a/wikipedia/src/main/java/org/wikipedia/Utils.java
+++ b/wikipedia/src/main/java/org/wikipedia/Utils.java
@@ -39,21 +39,37 @@
* @param newView The new view that should be faded in
*/
public static void crossFade(final View curView, final View newView) {
- newView.setAlpha(0f);
- newView.setVisibility(View.VISIBLE);
- newView.animate()
+ fadeIn(newView);
+ fadeOut(curView);
+ }
+
+ /**
+ * Fades in a view.
+ * @param view The currently invisible view to be faded in
+ */
+ public static void fadeIn(final View view) {
+ view.setAlpha(0f);
+ view.setVisibility(View.VISIBLE);
+ view.animate()
.alpha(1.0f)
.setDuration(WikipediaApp.MEDIUM_ANIMATION_DURATION)
- .setListener(null);
+ .setListener(null)
+ .start();
+ }
- curView.animate()
+ /**
+ * Fades out a view.
+ * @param view The currently visible view to be faded out
+ */
+ public static void fadeOut(final View view) {
+ view.animate()
.alpha(0f)
.setDuration(WikipediaApp.MEDIUM_ANIMATION_DURATION)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- curView.setVisibility(View.GONE);
- curView.setAlpha(1.0f);
+ view.setVisibility(View.GONE);
+ view.setAlpha(1.0f);
}
});
}
diff --git a/wikipedia/src/main/java/org/wikipedia/events/ShowToCEvent.java
b/wikipedia/src/main/java/org/wikipedia/events/ShowToCEvent.java
new file mode 100644
index 0000000..938384e
--- /dev/null
+++ b/wikipedia/src/main/java/org/wikipedia/events/ShowToCEvent.java
@@ -0,0 +1,4 @@
+package org.wikipedia.events;
+
+public class ShowToCEvent {
+}
diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageActionsHandler.java
b/wikipedia/src/main/java/org/wikipedia/page/PageActionsHandler.java
index 3dea537..322a4ef 100644
--- a/wikipedia/src/main/java/org/wikipedia/page/PageActionsHandler.java
+++ b/wikipedia/src/main/java/org/wikipedia/page/PageActionsHandler.java
@@ -6,10 +6,7 @@
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import org.wikipedia.R;
-import org.wikipedia.events.PageStateChangeEvent;
-import org.wikipedia.events.SavePageEvent;
-import org.wikipedia.events.SharePageEvent;
-import org.wikipedia.events.ShowOtherLanguagesEvent;
+import org.wikipedia.events.*;
public class PageActionsHandler implements PopupMenu.OnMenuItemClickListener {
private final PopupMenu menu;
@@ -39,11 +36,13 @@
menu.getMenu().findItem(R.id.menu_save_page).setEnabled(false);
menu.getMenu().findItem(R.id.menu_share_page).setEnabled(false);
menu.getMenu().findItem(R.id.menu_other_languages).setEnabled(false);
+ menu.getMenu().findItem(R.id.menu_show_toc).setEnabled(false);
break;
case PageViewFragment.STATE_COMPLETE_FETCH:
menu.getMenu().findItem(R.id.menu_save_page).setEnabled(true);
menu.getMenu().findItem(R.id.menu_share_page).setEnabled(true);
menu.getMenu().findItem(R.id.menu_other_languages).setEnabled(true);
+ menu.getMenu().findItem(R.id.menu_show_toc).setEnabled(true);
break;
default:
// How can this happen?!
@@ -63,6 +62,9 @@
case R.id.menu_other_languages:
bus.post(new ShowOtherLanguagesEvent());
break;
+ case R.id.menu_show_toc:
+ bus.post(new ShowToCEvent());
+ break;
default:
throw new RuntimeException("Unexpected menu item clicked");
}
diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageActivity.java
b/wikipedia/src/main/java/org/wikipedia/page/PageActivity.java
index 0c5f199..691d6a2 100644
--- a/wikipedia/src/main/java/org/wikipedia/page/PageActivity.java
+++ b/wikipedia/src/main/java/org/wikipedia/page/PageActivity.java
@@ -94,9 +94,14 @@
startActivity(shareIntent);
}
+ @Subscribe
+ public void onShowToCEvent(ShowToCEvent event) {
+ curPageFragment.showToC();
+ }
@Override
public void onBackPressed() {
- if (!searchAriclesFragment.handleBackPressed()) {
+ if ((curPageFragment != null && !curPageFragment.handleBackPressed())
+ || searchAriclesFragment.handleBackPressed()) {
if (getSupportFragmentManager().getBackStackEntryCount() <= 1) {
// Everything we could pop has been popped....
finish();
diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageViewFragment.java
b/wikipedia/src/main/java/org/wikipedia/page/PageViewFragment.java
index 59e1b28..3c45425 100644
--- a/wikipedia/src/main/java/org/wikipedia/page/PageViewFragment.java
+++ b/wikipedia/src/main/java/org/wikipedia/page/PageViewFragment.java
@@ -10,6 +10,7 @@
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.FrameLayout;
+import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Toast;
import org.json.JSONArray;
@@ -50,6 +51,8 @@
private View networkError;
private View retryButton;
+ private ListView tocList;
+
private Page page;
private HistoryEntry curEntry;
@@ -62,6 +65,8 @@
private int scrollY;
private int quickReturnBarId;
+
+ private View quickReturnBar;
// Pass in the id rather than the View object itself for the quickReturn
bar, to help it survive rotates
public PageViewFragment(PageTitle title, HistoryEntry historyEntry, int
quickReturnBarId) {
@@ -144,6 +149,8 @@
loadProgress = (ProgressBar)
parentView.findViewById(R.id.page_load_progress);
networkError = parentView.findViewById(R.id.page_error);
retryButton = parentView.findViewById(R.id.page_error_retry);
+ tocList = (ListView) parentView.findViewById(R.id.page_toc_list);
+ quickReturnBar = getActivity().findViewById(quickReturnBarId);
if (savedInstanceState != null &&
savedInstanceState.containsKey(KEY_TITLE)) {
title = savedInstanceState.getParcelable(KEY_TITLE);
@@ -184,7 +191,7 @@
performActionForState(state);
}
- new QuickReturnHandler(webView,
getActivity().findViewById(quickReturnBarId));
+ new QuickReturnHandler(webView, quickReturnBar);
return parentView;
}
@@ -317,4 +324,20 @@
}
}.execute();
}
+
+ private ToCHandler tocHandler;
+ public void showToC() {
+ if (tocHandler == null) {
+ tocHandler = new ToCHandler(tocList, page, quickReturnBar, bridge);
+ }
+ tocHandler.show();
+ }
+
+ public boolean handleBackPressed() {
+ if (tocHandler != null && tocHandler.isVisible()) {
+ tocHandler.hide();
+ return true;
+ }
+ return false;
+ }
}
diff --git a/wikipedia/src/main/java/org/wikipedia/page/ToCHandler.java
b/wikipedia/src/main/java/org/wikipedia/page/ToCHandler.java
new file mode 100644
index 0000000..dbbe617
--- /dev/null
+++ b/wikipedia/src/main/java/org/wikipedia/page/ToCHandler.java
@@ -0,0 +1,130 @@
+package org.wikipedia.page;
+
+import android.graphics.Color;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.*;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.wikipedia.*;
+
+import java.util.ArrayList;
+
+public class ToCHandler {
+ private final ListView tocList;
+ private final Page page;
+ private final View quickReturnBar;
+ private final CommunicationBridge bridge;
+
+ public ToCHandler(ListView tocList, Page page, View quickReturnBar,
CommunicationBridge bridge) {
+ this.tocList = tocList;
+ this.page = page;
+ this.quickReturnBar = quickReturnBar;
+ this.bridge = bridge;
+ }
+
+ private void scrollToSection(Section section) {
+ JSONObject payload = new JSONObject();
+ try {
+ payload.put("sectionID", section.getId());
+ } catch (JSONException e) {
+ // This won't happen
+ throw new RuntimeException(e);
+ }
+
+ bridge.sendMessage("scrollToSection", payload);
+ }
+
+ public void show() {
+ if (tocList.getAdapter() == null) {
+ TextView headerView = (TextView)
LayoutInflater.from(tocList.getContext()).inflate(R.layout.header_toc_list,
null, false);
+ headerView.setText(page.getTitle().getDisplayText());
+ tocList.addHeaderView(headerView);
+ headerView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ scrollToSection(page.getSections().get(0));
+ hide();
+ }
+ });
+
+ tocList.setAdapter(new ToCAdapter(page));
+ tocList.setOnItemClickListener(new
AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int
position, long id) {
+ Section section = (Section)
parent.getAdapter().getItem(position);
+ scrollToSection(section);
+ hide();
+ }
+ });
+ }
+ Utils.ensureTranslationY(quickReturnBar, -quickReturnBar.getHeight());
+ Utils.fadeIn(tocList);
+ }
+
+ public void hide() {
+ Utils.fadeOut(tocList);
+ Utils.ensureTranslationY(quickReturnBar, 0);
+ }
+
+ public boolean isVisible() {
+ return tocList.getVisibility() == View.VISIBLE;
+ }
+
+ private static class ToCAdapter extends BaseAdapter {
+ private final ArrayList<Section> sections;
+ private final PageTitle title;
+
+
+ private ToCAdapter(Page page) {
+ sections = new ArrayList<Section>();
+ for (Section s : page.getSections()) {
+ if (s.getLevel() < 3 && !s.isLead()) {
+ sections.add(s);
+ }
+ }
+ this.title = page.getTitle();
+ }
+
+ @Override
+ public int getCount() {
+ return sections.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return sections.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView =
LayoutInflater.from(parent.getContext()).inflate(R.layout.item_toc_entry,
parent, false);
+ }
+ Section section = (Section) getItem(position);
+ TextView sectionHeading = (TextView)
convertView.findViewById(R.id.page_toc_item_text);
+ View sectionFiller =
convertView.findViewById(R.id.page_toc_filler);
+
+ LinearLayout.LayoutParams indentLayoutParameters = new
LinearLayout.LayoutParams(sectionFiller.getLayoutParams());
+ indentLayoutParameters.width = (section.getLevel() - 1) * (int)(16
* WikipediaApp.SCREEN_DENSITY);
+ sectionFiller.setLayoutParams(indentLayoutParameters);
+
+ sectionHeading.setText(section.getHeading());
+
+ if (section.getLevel() > 1) {
+ sectionHeading.setTextColor(Color.parseColor("#898989"));
+ } else {
+ sectionHeading.setTextColor(Color.parseColor("#333333"));
+ }
+ return convertView;
+ }
+ }
+}
--
To view, visit https://gerrit.wikimedia.org/r/108029
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I475fefb3d0652cf96b1246489935528c7736d1c6
Gerrit-PatchSet: 2
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Yuvipanda <[email protected]>
Gerrit-Reviewer: Brion VIBBER <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits