summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2013-01-02 18:38:03 +0400
committerAndrew Dolgov <[email protected]>2013-01-02 18:38:03 +0400
commit723fff03ecb828eef700a0be2048349796123e27 (patch)
treeff0ea89889af839f2f86fd86d55273251aada1e4
parent1d8a003fe10752a195e0cc830e415a6829fce7d5 (diff)
cleaner titlewebview implementation
-rw-r--r--AndroidManifest.xml4
-rw-r--r--res/layout/article_fragment.xml90
-rw-r--r--src/android/webkit/WebViewClassic.java14
-rw-r--r--src/com/nobu_games/android/view/web/TitleBarWebView.java353
-rw-r--r--src/org/fox/ttrss/ArticleFragment.java16
-rw-r--r--src/org/fox/ttrss/TitleWebView.java91
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