diff options
-rw-r--r-- | AndroidManifest.xml | 4 | ||||
-rw-r--r-- | res/layout/article_fragment.xml | 90 | ||||
-rw-r--r-- | src/android/webkit/WebViewClassic.java | 14 | ||||
-rw-r--r-- | src/com/nobu_games/android/view/web/TitleBarWebView.java | 353 | ||||
-rw-r--r-- | src/org/fox/ttrss/ArticleFragment.java | 16 | ||||
-rw-r--r-- | src/org/fox/ttrss/TitleWebView.java | 91 |
6 files changed, 143 insertions, 425 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 3bf0f381..c6388116 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.fox.ttrss" - android:versionCode="126" - android:versionName="1.4" > + android:versionCode="127" + android:versionName="1.5" > <uses-sdk android:minSdkVersion="8" diff --git a/res/layout/article_fragment.xml b/res/layout/article_fragment.xml index b23ed643..c41f1549 100644 --- a/res/layout/article_fragment.xml +++ b/res/layout/article_fragment.xml @@ -2,8 +2,14 @@ android:id="@+id/article_fragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
- android:padding="5sp"
- android:orientation="vertical" > + android:orientation="vertical"
+ android:padding="5sp" >
+
+ <org.fox.ttrss.TitleWebView
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1" >
<LinearLayout
android:id="@+id/article_header"
@@ -14,22 +20,22 @@ <TextView
android:id="@+id/title"
- android:textColor="?linkColor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="There are many variations of passages of Lorem Ipsum available"
+ android:textColor="?linkColor"
android:textSize="16sp" />
<TextView
android:id="@+id/comments"
- android:textColor="?linkColor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="24 comments"
+ android:textColor="?linkColor"
android:textSize="13sp" />
-
+
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -40,12 +46,12 @@ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.7"
- android:textColor="?headlineExcerptTextColor"
android:ellipsize="end"
android:singleLine="true"
android:text="{TAGS}"
+ android:textColor="?headlineExcerptTextColor"
android:textSize="13sp" />
-
+
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
@@ -53,63 +59,55 @@ android:layout_weight="0.2"
android:gravity="right"
android:text="{DATE}"
- android:textColor="?headlineExcerptTextColor"
android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?headlineExcerptTextColor"
android:textSize="13sp"
android:textStyle="italic" />
-
</LinearLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_marginBottom="5sp"
android:layout_weight="0"
android:background="?horizontalDivider"
- android:layout_marginBottom="5sp"
android:paddingTop="2dip" />
-
</LinearLayout>
+ </org.fox.ttrss.TitleWebView>
+
+ <LinearLayout
+ android:id="@+id/attachments_holder"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0" >
- <com.nobu_games.android.view.web.TitleBarWebView
- android:id="@+id/content"
+ <Spinner
+ android:id="@+id/attachments"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:layout_weight="1"
- />
+ android:prompt="@string/attachments_prompt" />
- <LinearLayout
- android:id="@+id/attachments_holder"
- android:layout_width="match_parent"
+ <Button
+ android:id="@+id/attachment_view"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="0" >
+ android:layout_weight="0"
+ android:text="@string/attachment_view" />
- <Spinner
- android:id="@+id/attachments"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:prompt="@string/attachments_prompt" />
+ <Button
+ android:id="@+id/attachment_share"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:text="@string/attachment_share" />
- <Button
- android:id="@+id/attachment_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="0"
- android:text="@string/attachment_view" />
+ <Button
+ android:id="@+id/attachment_copy"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:text="@string/attachment_copy" />
+ </LinearLayout>
- <Button
- android:id="@+id/attachment_share"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="0"
- android:text="@string/attachment_share" />
-
- <Button
- android:id="@+id/attachment_copy"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="0"
- android:text="@string/attachment_copy" />
- </LinearLayout>
-
</LinearLayout>
\ No newline at end of file diff --git a/src/android/webkit/WebViewClassic.java b/src/android/webkit/WebViewClassic.java deleted file mode 100644 index e315beea..00000000 --- a/src/android/webkit/WebViewClassic.java +++ /dev/null @@ -1,14 +0,0 @@ -package android.webkit; - -import android.view.View; - -/** - * Trojan class for getting access to a hidden API level 16 interface - */ -public class WebViewClassic { - public interface TitleBarDelegate { - int getTitleHeight(); - - public void onSetEmbeddedTitleBar(final View title); - } -} diff --git a/src/com/nobu_games/android/view/web/TitleBarWebView.java b/src/com/nobu_games/android/view/web/TitleBarWebView.java deleted file mode 100644 index 4931bed0..00000000 --- a/src/com/nobu_games/android/view/web/TitleBarWebView.java +++ /dev/null @@ -1,353 +0,0 @@ -package com.nobu_games.android.view.web; - -/* - * Copyright (C) 2012 Thomas Werner - * Portions Copyright (C) 2006 The Android Open Source Project - * Portions Copyright (C) 2012 The K-9 Dog Walkers - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.lang.reflect.Method; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.util.AttributeSet; -import android.util.Log; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.webkit.WebView; -import android.webkit.WebViewClassic.TitleBarDelegate; -import android.widget.FrameLayout; - -/** - * WebView derivative with custom setEmbeddedTitleBar implementation for Android - * versions that do not support that feature anymore. - * <p> - * <b>Usage</b> - * <p> - * Call {@link #setEmbeddedTitleBarCompat(View)} for setting a view as embedded - * title bar on top of the displayed WebView page. - */ -public class TitleBarWebView extends WebView implements TitleBarDelegate { - /** - * Internally used view wrapper for suppressing unwanted touch events on the - * title bar view when WebView contents is being touched. - */ - private class TouchBlockView extends FrameLayout { - public TouchBlockView(Context context) { - super(context); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - if(!mTouchInTitleBar) { - return false; - } else { - switch(ev.getAction() & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - mTouchInTitleBar = false; - break; - - default: - - } - - return super.dispatchTouchEvent(ev); - } - } - } - - private static final String TAG = "TitleBarWebView"; - View mTitleBar; - int mTitleBarOffs; - boolean mTouchInTitleBar; - boolean mTouchMove; - private Rect mClipBounds = new Rect(); - private Matrix mMatrix = new Matrix(); - private Method mNativeGetVisibleTitleHeightMethod; - - /** - * This will always contain a reference to the title bar view no matter if - * {@code setEmbeddedTitleBar()} or the Jelly Bean workaround is used. We use this in - * {@link #getTitleHeight()}. - */ - private View mTitleBarView; - - public TitleBarWebView(Context context) { - super(context); - init(); - } - - public TitleBarWebView(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public TitleBarWebView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(); - } - - /** - * <i>Corrects the visual displacement caused by the title bar view.</i> - * <p> - * {@inheritDoc} - */ - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - if(mTitleBar != null) { - final int sy = getScrollY(); - final int visTitleHeight = getVisibleTitleHeightCompat(); - final float x = event.getX(); - float y = event.getY(); - - switch(event.getAction() & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - if(y <= visTitleHeight) { - mTouchInTitleBar = true; - } - break; - - case MotionEvent.ACTION_MOVE: - mTouchMove = true; - break; - - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - mTouchMove = false; - break; - - default: - } - - if(mTouchInTitleBar) { - y += sy; - event.setLocation(x, y); - - return mTitleBar.dispatchTouchEvent(event); - } else { - if(Build.VERSION.SDK_INT < 16) { - if(!mTouchMove) { - mTitleBarOffs = getVisibleTitleHeightCompat(); - } - - y -= mTitleBarOffs; - if(y < 0) y = 0; - event.setLocation(x, y); - } - - return super.dispatchTouchEvent(event); - } - } else { - return super.dispatchTouchEvent(event); - } - } - - /** - * Sets a {@link View} as an embedded title bar to appear on top of the - * WebView page. - * <p> - * This method tries to call the hidden API method setEmbeddedTitleBar if - * present. On failure the custom implementation provided by this class will - * be used instead. - * - * @param v The view to set or null for removing the title bar view. - */ - public void setEmbeddedTitleBarCompat(View v) { - try { - Method nativeMethod = getClass().getMethod("setEmbeddedTitleBar", - View.class); - nativeMethod.invoke(this, v); - } catch(Exception e) { - Log.d(TAG, - "Native setEmbeddedTitleBar not available. Starting workaround"); - setEmbeddedTitleBarJellyBean(v); - } - - mTitleBarView = v; - } - - @Override - protected int computeVerticalScrollExtent() { - if(mTitleBar == null) return super.computeVerticalScrollExtent(); - return getViewHeightWithTitle() - getVisibleTitleHeightCompat(); - } - - @Override - protected int computeVerticalScrollOffset() { - if(mTitleBar == null) return super.computeVerticalScrollOffset(); - return Math.max(getScrollY() - getTitleHeight(), 0); - } - - @Override - protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - canvas.save(); - - if(child == mTitleBar) { - mTitleBar.offsetLeftAndRight(getScrollX() - mTitleBar.getLeft()); - - if(Build.VERSION.SDK_INT < 16) { - mMatrix.set(canvas.getMatrix()); - mMatrix.postTranslate(0, -getScrollY()); - canvas.setMatrix(mMatrix); - } - } - - boolean result = super.drawChild(canvas, child, drawingTime); - canvas.restore(); - - return result; - } - - /** - * Gets the currently visible height of the title bar view if set. - * - * @return Visible height of title bar view or 0 if not set. - */ - protected int getVisibleTitleHeightCompat() { - if(mTitleBar == null && mNativeGetVisibleTitleHeightMethod != null) { - try { - return (Integer) mNativeGetVisibleTitleHeightMethod - .invoke(this); - } catch(Exception e) { - } - } - - return Math.max(getTitleHeight() - Math.max(0, getScrollY()), 0); - } - - @Override - protected void onDraw(Canvas canvas) { - if (Build.VERSION.SDK_INT >= 16) { - super.onDraw(canvas); - return; - } - - canvas.save(); - - if(mTitleBar != null) { - final int sy = getScrollY(); - final int sx = getScrollX(); - mClipBounds.top = sy; - mClipBounds.left = sx; - mClipBounds.right = mClipBounds.left + getWidth(); - mClipBounds.bottom = mClipBounds.top + getHeight(); - canvas.clipRect(mClipBounds); - mMatrix.set(canvas.getMatrix()); - int titleBarOffs = getVisibleTitleHeightCompat(); - if(titleBarOffs < 0) titleBarOffs = 0; - mMatrix.postTranslate(0, titleBarOffs); - canvas.setMatrix(mMatrix); - } - - super.onDraw(canvas); - canvas.restore(); - } - - /** - * Overrides a hidden method by replicating the behavior of the original - * WebView class from Android 2.3.4. - * <p> - * The worst that could happen is that this method never gets called, which - * isn't too bad because this does not harm the functionality of this class. - */ - protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, - int l, int t, int r, int b) { - int sy = getScrollY(); - - if(sy < 0) { - t -= sy; - } - scrollBar.setBounds(l, t + getVisibleTitleHeightCompat(), r, b); - scrollBar.draw(canvas); - } - - /** - * Get the height of the title bar view. - * - * <p> - * In the Jelly Bean workaround we need this method because we have to implement the - * {@link TitleBarDelegate} interface. But by implementing this method we override the hidden - * {@code getTitleHeight()} of the {@link WebView}s in older Android versions. - * <br> - * What we should do, is return the title height on Jelly Bean and call through to the parent - * class on older Android versions. But this would require even more trickery, so we just - * inline the parent functionality which simply calls {@link View#getHeight()}. This is exactly - * what we do on Jelly Bean anyway. - * </p> - */ - @Override - public int getTitleHeight() { - if (mTitleBarView != null) { - return mTitleBarView.getHeight(); - } - return 0; - } - - private int getViewHeightWithTitle() { - int height = getHeight(); - if(isHorizontalScrollBarEnabled() && !overlayHorizontalScrollbar()) { - height -= getHorizontalScrollbarHeight(); - } - return height; - } - - private void init() { - try { - mNativeGetVisibleTitleHeightMethod = WebView.class - .getDeclaredMethod("getVisibleTitleHeight"); - } catch(NoSuchMethodException e) { - Log.w(TAG, - "Could not retrieve native hidden getVisibleTitleHeight method"); - } - } - - /** - * The hidden method setEmbeddedTitleBar has been removed from Jelly Bean. - * This method replicates the functionality. - * - * @param v - */ - private void setEmbeddedTitleBarJellyBean(View v) { - if(mTitleBar == v) return; - - if(mTitleBar != null) { - removeView(mTitleBar); - } - - if(null != v) { - LayoutParams vParams = new LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0); - - TouchBlockView tbv = new TouchBlockView(getContext()); - FrameLayout.LayoutParams tbvParams = new FrameLayout.LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); - tbv.addView(v, tbvParams); - addView(tbv, vParams); - v = tbv; - } - - mTitleBar = v; - } - - @Override - public void onSetEmbeddedTitleBar(View title) { /* unused */ } -} diff --git a/src/org/fox/ttrss/ArticleFragment.java b/src/org/fox/ttrss/ArticleFragment.java index 38b66290..7372487d 100644 --- a/src/org/fox/ttrss/ArticleFragment.java +++ b/src/org/fox/ttrss/ArticleFragment.java @@ -13,23 +13,19 @@ import org.jsoup.nodes.Document; import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
-import com.nobu_games.android.view.web.TitleBarWebView;
-
import android.annotation.SuppressLint;
-import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.graphics.Paint;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.util.TypedValue;
-import android.view.GestureDetector;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
+import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
@@ -42,7 +38,6 @@ import android.webkit.WebSettings.LayoutAlgorithm; import android.webkit.WebView;
import android.widget.ArrayAdapter;
import android.widget.Button;
-import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
@@ -174,16 +169,17 @@ public class ArticleFragment extends Fragment implements GestureDetector.OnDoubl }
}
- TitleBarWebView web = (TitleBarWebView)view.findViewById(R.id.content);
+ TitleWebView web = (TitleWebView)view.findViewById(R.id.content);
if (web != null) {
- if (!m_activity.isPortrait() && m_activity.isSmallScreen()) {
+ /* if (!m_activity.isPortrait() && m_activity.isSmallScreen()) {
+
View header = view.findViewById(R.id.article_header);
LinearLayout article = (LinearLayout)view.findViewById(R.id.article_fragment);
article.removeView(header);
-
+
web.setEmbeddedTitleBarCompat(header);
- }
+ } */
web.setWebChromeClient(new WebChromeClient() {
@Override
diff --git a/src/org/fox/ttrss/TitleWebView.java b/src/org/fox/ttrss/TitleWebView.java new file mode 100644 index 00000000..e39fc268 --- /dev/null +++ b/src/org/fox/ttrss/TitleWebView.java @@ -0,0 +1,91 @@ +package org.fox.ttrss;
+
+// http://www.techques.com/question/1-9718245/Webview-in-Scrollview
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.webkit.WebView;
+
+public class TitleWebView extends WebView{
+
+ public TitleWebView(Context context, AttributeSet attrs){
+ super(context, attrs);
+ }
+
+ private int titleHeight;
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ // determine height of title bar
+ View title = getChildAt(0);
+ titleHeight = title==null ? 0 : title.getMeasuredHeight();
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev){
+ return true; // don't pass our touch events to children (title bar), we send these in dispatchTouchEvent
+ }
+
+ private boolean touchInTitleBar;
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent me){
+
+ boolean wasInTitle = false;
+ switch(me.getActionMasked()){
+ case MotionEvent.ACTION_DOWN:
+ touchInTitleBar = (me.getY() <= visibleTitleHeight());
+ break;
+
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ wasInTitle = touchInTitleBar;
+ touchInTitleBar = false;
+ break;
+ }
+ if(touchInTitleBar || wasInTitle) {
+ View title = getChildAt(0);
+ if(title!=null) {
+ // this touch belongs to title bar, dispatch it here
+ me.offsetLocation(0, getScrollY());
+ return title.dispatchTouchEvent(me);
+ }
+ }
+ // this is our touch, offset and process
+ me.offsetLocation(0, -titleHeight);
+ return super.dispatchTouchEvent(me);
+ }
+
+ /**
+ * @return visible height of title (may return negative values)
+ */
+ private int visibleTitleHeight(){
+ return titleHeight-getScrollY();
+ }
+
+ @Override
+ protected void onScrollChanged(int l, int t, int oldl, int oldt){
+ super.onScrollChanged(l, t, oldl, oldt);
+ View title = getChildAt(0);
+ if(title!=null) // undo horizontal scroll, so that title scrolls only vertically
+ title.offsetLeftAndRight(l - title.getLeft());
+ }
+
+ @Override
+ protected void onDraw(Canvas c){
+
+ c.save();
+ int tH = visibleTitleHeight();
+ if(tH>0) {
+ // clip so that it doesn't clear background under title bar
+ int sx = getScrollX(), sy = getScrollY();
+ c.clipRect(sx, sy+tH, sx+getWidth(), sy+getHeight());
+ }
+ c.translate(0, titleHeight);
+ super.onDraw(c);
+ c.restore();
+ }
+ }
\ No newline at end of file |