cleaner titlewebview implementation
This commit is contained in:
parent
1d8a003fe1
commit
723fff03ec
@ -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"
|
||||
|
@ -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,20 +20,20 @@
|
||||
|
||||
<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
|
||||
@ -40,10 +46,10 @@
|
||||
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
|
||||
@ -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>
|
||||
|
||||
<com.nobu_games.android.view.web.TitleBarWebView
|
||||
android:id="@+id/content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
<LinearLayout
|
||||
android:id="@+id/attachments_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0" >
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/attachments_holder"
|
||||
<Spinner
|
||||
android:id="@+id/attachments"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0" >
|
||||
android:layout_weight="1"
|
||||
android:prompt="@string/attachments_prompt" />
|
||||
|
||||
<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_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_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_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_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>
|
||||
<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>
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 */ }
|
||||
}
|
@ -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
|
||||
|
91
src/org/fox/ttrss/TitleWebView.java
Normal file
91
src/org/fox/ttrss/TitleWebView.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user