summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorXimeng Zu <uznomis@yahoo.com>2017-05-24 17:02:17 -0500
committerTomaž Vajngerl <quikee@gmail.com>2017-07-11 10:52:19 +0200
commit6b873439042960bfc72a5e341c5ed61eeb40f53e (patch)
tree0415afc622d0576b63f41cc0e56d0e96a8996685 /android
parentff10bc47abe0b04480c9fb5db025afbb5e402b4b (diff)
Presentation Mode
Adding fullscreen presentation mode. Change-Id: Id07416ce204d1d7dd917fbd33a4d9f5072ac1703 Reviewed-on: https://gerrit.libreoffice.org/38006 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> Tested-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'android')
-rw-r--r--android/source/AndroidManifest.xml7
-rw-r--r--android/source/res/layout/presentation_mode.xml45
-rw-r--r--android/source/res/menu/main.xml5
-rw-r--r--android/source/res/values/strings.xml4
-rw-r--r--android/source/src/java/org/libreoffice/LOKitTileProvider.java52
-rwxr-xr-xandroid/source/src/java/org/libreoffice/LibreOfficeMainActivity.java41
-rw-r--r--android/source/src/java/org/libreoffice/PresentationActivity.java188
-rw-r--r--android/source/src/java/org/libreoffice/ToolbarController.java3
8 files changed, 329 insertions, 16 deletions
diff --git a/android/source/AndroidManifest.xml b/android/source/AndroidManifest.xml
index 0b384a3becc2..a9c3a3a1609d 100644
--- a/android/source/AndroidManifest.xml
+++ b/android/source/AndroidManifest.xml
@@ -125,6 +125,13 @@
android:windowSoftInputMode="stateHidden">
</activity>
+ <activity android:name=".PresentationActivity"
+ android:screenOrientation="landscape" >
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".LibreOfficeMainActivity" />
+ </activity>
+
</application>
</manifest>
diff --git a/android/source/res/layout/presentation_mode.xml b/android/source/res/layout/presentation_mode.xml
new file mode 100644
index 000000000000..ec1845ab68ab
--- /dev/null
+++ b/android/source/res/layout/presentation_mode.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent" android:layout_height="match_parent">
+
+ <WebView
+ android:id="@+id/presentation_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <RelativeLayout
+ android:id="@+id/presentation_gesture_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:animateLayoutChanges="true">
+
+ <ImageButton
+ android:id="@+id/slide_show_nav_prev"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:src="@drawable/ic_search_direction_up" />
+
+ <ImageButton
+ android:id="@+id/slide_show_nav_next"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:src="@drawable/ic_search_direction_down" />
+
+ <Button
+ android:id="@+id/slide_show_nav_back"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ android:text="@string/slideshow_action_back" />
+
+ </RelativeLayout>
+
+</RelativeLayout> \ No newline at end of file
diff --git a/android/source/res/menu/main.xml b/android/source/res/menu/main.xml
index 3ec0dadc5b63..0b34d8b5ffac 100644
--- a/android/source/res/menu/main.xml
+++ b/android/source/res/menu/main.xml
@@ -42,6 +42,11 @@
android:orderInCategory="100" />
</group>
+ <item android:id="@+id/action_presentation"
+ android:title="@string/action_presentation"
+ android:orderInCategory="100"
+ android:enabled="false" />
+
<item android:id="@+id/action_parts"
android:title="@string/action_parts"
android:orderInCategory="100" />
diff --git a/android/source/res/values/strings.xml b/android/source/res/values/strings.xml
index 4495ca584927..ad4d2699684a 100644
--- a/android/source/res/values/strings.xml
+++ b/android/source/res/values/strings.xml
@@ -130,5 +130,9 @@
<!-- Create New Document Dialog Strings -->
<string name="create_new_document_title">Enter file name</string>
<string name="action_create">CREATE</string>
+ <string name="action_presentation">Slide show</string>
+ <string name="alert_copy_svg_slide_show_to_clipboard">Your Android device doesn\'t support in-app svg slideshow. We copied the slideshow link to clipboard. Please press home button, open a modern web browser, paste in the address bar, and go.</string>
+ <string name="alert_copy_svg_slide_show_to_clipboard_dismiss">OK</string>
+ <string name="slideshow_action_back">Back</string>
</resources>
diff --git a/android/source/src/java/org/libreoffice/LOKitTileProvider.java b/android/source/src/java/org/libreoffice/LOKitTileProvider.java
index e17893985a75..6fb8a9b80671 100644
--- a/android/source/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/source/src/java/org/libreoffice/LOKitTileProvider.java
@@ -101,6 +101,10 @@ class LOKitTileProvider implements TileProvider {
Log.i(LOGTAG, "Document parts: " + parts);
mContext.getDocumentPartView().clear();
+ if (mDocument.getDocumentType() == Document.DOCTYPE_PRESENTATION) {
+ mContext.getToolbarController().disableMenuItem(R.id.action_presentation, false);
+ }
+
// Writer documents always have one part, so hide the navigation drawer.
if (mDocument.getDocumentType() != Document.DOCTYPE_TEXT) {
for (int i = 0; i < parts; i++) {
@@ -134,26 +138,44 @@ class LOKitTileProvider implements TileProvider {
@Override
public void saveDocumentAs(String filePath, String format) {
- String newFilePath = "file://" + filePath;
+ final String newFilePath = "file://" + filePath;
Log.d("saveFilePathURL", newFilePath);
+ LOKitShell.showProgressSpinner(mContext);
mDocument.saveAs(newFilePath, format, "");
if (!mOffice.getError().isEmpty()){
Log.e("Save Error", mOffice.getError());
- LOKitShell.getMainHandler().post(new Runnable() {
- @Override
- public void run() {
- // There was some error
- mContext.showSaveStatusMessage(true);
- }
- });
- }
- LOKitShell.getMainHandler().post(new Runnable() {
- @Override
- public void run() {
- // There was no error
- mContext.showSaveStatusMessage(false);
+ if (format.equals("svg")) {
+ // error in creating temp slideshow svg file
+ Log.d(LOGTAG, "Error in creating temp slideshow svg file");
+ } else {
+ LOKitShell.getMainHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ // There was some error
+ mContext.showSaveStatusMessage(true);
+ }
+ });
}
- });
+ } else {
+ if (format.equals("svg")) {
+ // successfully created temp slideshow svg file
+ LOKitShell.getMainHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ mContext.startPresentation(newFilePath);
+ }
+ });
+ } else {
+ LOKitShell.getMainHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ // There was no error
+ mContext.showSaveStatusMessage(false);
+ }
+ });
+ }
+ }
+ LOKitShell.hideProgressSpinner(mContext);
}
private void setupDocumentFonts() {
diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
index b4f8dc77f60b..8aeb1f5ff816 100755
--- a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -2,6 +2,8 @@ package org.libreoffice;
import android.app.Activity;
import android.app.AlertDialog;
+import android.content.ClipData;
+import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
@@ -10,12 +12,14 @@ import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.graphics.RectF;
+import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
-import android.support.design.widget.Snackbar;
import android.support.design.widget.BottomSheetBehavior;
+import android.support.design.widget.Snackbar;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
@@ -79,6 +83,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
private File mInputFile;
private DocumentOverlay mDocumentOverlay;
private File mTempFile = null;
+ private File mTempSlideShowFile = null;
private String newDocumentType = null;
BottomSheetBehavior bottomToolbarSheetBehavior;
@@ -407,6 +412,10 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
// noinspection ResultOfMethodCallIgnored
mTempFile.delete();
}
+ if (mTempSlideShowFile.exists()) {
+ // noinspection ResultOfMethodCallIgnored
+ mTempSlideShowFile.delete();
+ }
}
}
@Override
@@ -749,6 +758,36 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
Snackbar.make(mDrawerLayout, getString(R.string.create_new_file_success) + mInputFile.getName(), Snackbar.LENGTH_LONG).show();
else
Snackbar.make(mDrawerLayout, getString(R.string.create_new_file_error) + mInputFile.getName(), Snackbar.LENGTH_LONG).show(); }
+
+ public void preparePresentation() {
+ if (getExternalCacheDir() != null) {
+ String tempPath = getExternalCacheDir().getPath() + "/" + mInputFile.getName() + ".svg";
+ mTempSlideShowFile = new File(tempPath);
+ if (mTempSlideShowFile.exists() && !isDocumentChanged) {
+ startPresentation("file://" + tempPath);
+ } else {
+ LOKitShell.sendSaveAsEvent(tempPath, "svg");
+ }
+ }
+ }
+
+ public void startPresentation(String tempPath) {
+ // pre-KitKat android doesn't have chrome-based WebView, which is needed to show svg slideshow
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ Intent intent = new Intent(this, PresentationActivity.class);
+ intent.setData(Uri.parse(tempPath));
+ startActivity(intent);
+ } else {
+ // copy the svg file path to clipboard for the user to paste in a browser
+ ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipData clip = ClipData.newPlainText("temp svg file path", tempPath);
+ clipboard.setPrimaryClip(clip);
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setMessage(R.string.alert_copy_svg_slide_show_to_clipboard)
+ .setPositiveButton(R.string.alert_copy_svg_slide_show_to_clipboard_dismiss, null).show();
+ }
+ }
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/source/src/java/org/libreoffice/PresentationActivity.java b/android/source/src/java/org/libreoffice/PresentationActivity.java
new file mode 100644
index 000000000000..1eea5e3836fb
--- /dev/null
+++ b/android/source/src/java/org/libreoffice/PresentationActivity.java
@@ -0,0 +1,188 @@
+package org.libreoffice;
+
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.view.GestureDetectorCompat;
+import android.support.v7.app.AppCompatActivity;
+import android.view.GestureDetector;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.webkit.WebView;
+import android.widget.Button;
+import android.widget.ImageButton;
+
+public class PresentationActivity extends AppCompatActivity {
+
+ private static final String LOGTAG = PresentationActivity.class.getSimpleName();
+ WebView mWebView;
+ View mGestureView;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // First we hide the status bar
+ if (Build.VERSION.SDK_INT < 16) {
+ // If the Android version is lower than Jellybean, use this call to hide
+ // the status bar.
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ } else {
+ // If higher than Jellybean
+ View decorView = getWindow().getDecorView();
+ // Hide the status bar.
+ int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
+ decorView.setSystemUiVisibility(uiOptions);
+ }
+
+ setContentView(R.layout.presentation_mode);
+
+ // get intent and url
+ Intent intent = getIntent();
+ String filePath = intent.getDataString();
+
+ // set up WebView
+ mWebView = (WebView) findViewById(R.id.presentation_view);
+ mWebView.getSettings().setJavaScriptEnabled(true);
+ mWebView.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return true;
+ }
+ });
+
+ // set up buttons within presentation_gesture_view
+ ImageButton prevButton = (ImageButton) findViewById(R.id.slide_show_nav_prev);
+ ImageButton nextButton = (ImageButton) findViewById(R.id.slide_show_nav_next);
+ Button backButton = (Button) findViewById(R.id.slide_show_nav_back);
+
+ prevButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ pageLeft();
+ }
+ });
+ nextButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ pageRight();
+ }
+ });
+ backButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onBackPressed();
+ }
+ });
+
+ // set up presentation_gesture_view
+ mGestureView = findViewById(R.id.presentation_gesture_view);
+ final GestureDetectorCompat gestureDetector =
+ new GestureDetectorCompat(this, new presentationGestureViewListener());
+ mGestureView.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return gestureDetector.onTouchEvent(event);
+ }
+ });
+
+ // load url
+ mWebView.loadUrl(filePath);
+ }
+
+ private class presentationGestureViewListener extends GestureDetector.SimpleOnGestureListener {
+ private static final int SWIPE_VELOCITY_THRESHOLD = 100;
+ private static final int SCROLL_THRESHOLD = 10; // if scrollCounter is larger than this, a page switch is triggered
+ private int scrollCounter = 0; // a counter for measuring scrolling distance
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return true;
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ boolean result = false;
+ try {
+ float diffY = e2.getY() - e1.getY();
+ float diffX = e2.getX() - e1.getX();
+ if (Math.abs(diffX) > Math.abs(diffY)) {
+ if (Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
+ if (diffX > 0) {
+ pageRight();
+ } else {
+ pageLeft();
+ }
+ result = true;
+ }
+ }
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ return result;
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ boolean result = false;
+ try {
+ float diffY = e2.getY() - e1.getY();
+ float diffX = e2.getX() - e1.getX();
+ if (Math.abs(diffX) < Math.abs(diffY)) {
+ if (distanceY > 0) {
+ scrollCounter++;
+ if (scrollCounter >= SCROLL_THRESHOLD) {
+ pageRight();
+ scrollCounter = 0;
+ }
+ } else {
+ scrollCounter--;
+ if (scrollCounter <= -SCROLL_THRESHOLD) {
+ pageLeft();
+ scrollCounter = 0;
+ }
+ }
+ result = true;
+ }
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ return result;
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ if (e.getX() < mGestureView.getWidth()/3) {
+ pageLeft();
+ } else if (e.getX() < mGestureView.getWidth()*2/3) {
+ hideControlButtons();
+ } else {
+ pageRight();
+ }
+ return true;
+ }
+ }
+
+ private void hideControlButtons() {
+ View[] views= {findViewById(R.id.slide_show_nav_prev),findViewById(R.id.slide_show_nav_next),findViewById(R.id.slide_show_nav_back)} ;
+ for (View view : views) {
+ if (view.getVisibility() == View.GONE) {
+ view.setVisibility(View.VISIBLE);
+ } else if (view.getVisibility() == View.VISIBLE) {
+ view.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ private void pageLeft() {
+ mWebView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT));
+ }
+
+ private void pageRight() {
+ mWebView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT));
+ }
+} \ No newline at end of file
diff --git a/android/source/src/java/org/libreoffice/ToolbarController.java b/android/source/src/java/org/libreoffice/ToolbarController.java
index d7f1ac18c95e..9ef994d271a9 100644
--- a/android/source/src/java/org/libreoffice/ToolbarController.java
+++ b/android/source/src/java/org/libreoffice/ToolbarController.java
@@ -132,6 +132,9 @@ public class ToolbarController implements Toolbar.OnMenuItemClickListener {
case R.id.action_redo:
LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Redo"));
return true;
+ case R.id.action_presentation:
+ mContext.preparePresentation();
+ return true;
}
return false;
}