Add SearchBar list animation

This commit is contained in:
seven332 committed 2015-04-21 18:58:52 +08:00
1 parent 708ba3a3e9
commit beec5d8776
18 files changed
+1523 -11

No files matched your search

-1
View File
@@ -86,7 +86,6 @@
</content>
<orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="cardview-v7-22.0.0" level="project" />
<orderEntry type="library" exported="" name="support-v4-22.0.0" level="project" />
<orderEntry type="library" exported="" name="svg-android-2.0.6" level="project" />
<orderEntry type="library" exported="" name="support-annotations-22.0.0" level="project" />
-1
View File
@@ -27,7 +27,6 @@ dependencies {
compile 'com.android.support:support-v4:22.0.0'
compile 'com.android.support:appcompat-v7:22.0.0'
compile 'com.android.support:recyclerview-v7:22.0.0'
compile 'com.android.support:cardview-v7:22.0.0'
compile 'com.github.japgolly.android:svg-android:2.0.6'
compile fileTree(dir: 'libs', include: ['*.jar'])
}
+5 -1
View File
@@ -44,6 +44,10 @@
void setProgress(float);
float getProgress();
}
-keepclassmembers class com.hippo.ehviewer.widget.SearchBar {
void setProgress(float);
float getProgress();
}
#For VectorResources
-keep class android.content.res.VectorResources {*;}
-keepclassmembers class android.content.res.VectorResources {*;}
@@ -0,0 +1,401 @@
/*
* Copyright (C) 2015 Hippo Seven
*
* 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
* 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.
*/
package android.support.v7.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import com.hippo.ehviewer.R;
/**
* A FrameLayout with a rounded corner background and shadow.
* <p>
* CardView uses <code>elevation</code> property on L for shadows and falls back to a custom shadow
* implementation on older platforms.
* <p>
* Due to expensive nature of rounded corner clipping, on platforms before L, CardView does not
* clip its children that intersect with rounded corners. Instead, it adds padding to avoid such
* intersection (See {@link #setPreventCornerOverlap(boolean)} to change this behavior).
* <p>
* Before L, CardView adds padding to its content and draws shadows to that area. This padding
* amount is equal to <code>maxCardElevation + (1 - cos45) * cornerRadius</code> on the sides and
* <code>maxCardElevation * 1.5 + (1 - cos45) * cornerRadius</code> on top and bottom.
* <p>
* Since padding is used to offset content for shadows, you cannot set padding on CardView.
* Instead,
* you can use content padding attributes in XML or {@link #setContentPadding(int, int, int, int)}
* in code to set the padding between the edges of the Card and children of CardView.
* <p>
* Note that, if you specify exact dimensions for the CardView, because of the shadows, its content
* area will be different between platforms before L and after L. By using api version specific
* resource values, you can avoid these changes. Alternatively, If you want CardView to add inner
* padding on platforms L and after as well, you can set {@link #setUseCompatPadding(boolean)} to
* <code>true</code>.
* <p>
* To change CardView's elevation in a backward compatible way, use
* {@link #setCardElevation(float)}. CardView will use elevation API on L and before L, it will
* change the shadow size. To avoid moving the View while shadow size is changing, shadow size is
* clamped by {@link #getMaxCardElevation()}. If you want to change elevation dynamically, you
* should call {@link #setMaxCardElevation(float)} when CardView is initialized.
*
* @attr ref android.support.v7.cardview.R.styleable#CardView_cardBackgroundColor
* @attr ref android.support.v7.cardview.R.styleable#CardView_cardCornerRadius
* @attr ref android.support.v7.cardview.R.styleable#CardView_cardElevation
* @attr ref android.support.v7.cardview.R.styleable#CardView_cardMaxElevation
* @attr ref android.support.v7.cardview.R.styleable#CardView_cardUseCompatPadding
* @attr ref android.support.v7.cardview.R.styleable#CardView_cardPreventCornerOverlap
* @attr ref android.support.v7.cardview.R.styleable#CardView_contentPadding
* @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingLeft
* @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingTop
* @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingRight
* @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingBottom
*/
public class CardView extends FrameLayout implements CardViewDelegate {
private static final CardViewImpl NO_ELEVATION_IMPL;
private static final CardViewImpl IMPL;
private CardViewImpl mImpl;
static {
if (Build.VERSION.SDK_INT >= 21) {
IMPL = new CardViewApi21();
NO_ELEVATION_IMPL = new CardViewJellybeanMr1();
} else if (Build.VERSION.SDK_INT >= 17) {
IMPL = new CardViewJellybeanMr1();
NO_ELEVATION_IMPL = IMPL;
} else {
IMPL = new CardViewEclairMr1();
NO_ELEVATION_IMPL = IMPL;
}
IMPL.initStatic();
NO_ELEVATION_IMPL.initStatic();
}
private boolean mCompatPadding;
private boolean mPreventCornerOverlap;
private final Rect mContentPadding = new Rect();
private final Rect mShadowBounds = new Rect();
public CardView(Context context) {
super(context);
initialize(context, null, 0);
}
public CardView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context, attrs, 0);
}
public CardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context, attrs, defStyleAttr);
}
@Override
public void setPadding(int left, int top, int right, int bottom) {
// NO OP
}
@Override
public void setPaddingRelative(int start, int top, int end, int bottom) {
// NO OP
}
/**
* Returns whether CardView will add inner padding on platforms L and after.
*
* @return True CardView adds inner padding on platforms L and after to have same dimensions
* with platforms before L.
*/
@Override
public boolean getUseCompatPadding() {
return mCompatPadding;
}
/**
* CardView adds additional padding to draw shadows on platforms before L.
* <p>
* This may cause Cards to have different sizes between L and before L. If you need to align
* CardView with other Views, you may need api version specific dimension resources to account
* for the changes.
* As an alternative, you can set this flag to <code>true</code> and CardView will add the same
* padding values on platforms L and after.
* <p>
* Since setting this flag to true adds unnecessary gaps in the UI, default value is
* <code>false</code>.
*
* @param useCompatPadding True if CardView should add padding for the shadows on platforms L
* and above.
* @attr ref android.support.v7.cardview.R.styleable#CardView_cardUseCompatPadding
*/
public void setUseCompatPadding(boolean useCompatPadding) {
if (mCompatPadding == useCompatPadding) {
return;
}
mCompatPadding = useCompatPadding;
mImpl.onCompatPaddingChanged(this);
}
/**
* Sets the padding between the Card's edges and the children of CardView.
* <p>
* Depending on platform version or {@link #getUseCompatPadding()} settings, CardView may
* update these values before calling {@link android.view.View#setPadding(int, int, int, int)}.
*
* @param left The left padding in pixels
* @param top The top padding in pixels
* @param right The right padding in pixels
* @param bottom The bottom padding in pixels
* @attr ref android.support.v7.cardview.R.styleable#CardView_contentPadding
* @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingLeft
* @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingTop
* @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingRight
* @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingBottom
*/
public void setContentPadding(int left, int top, int right, int bottom) {
mContentPadding.set(left, top, right, bottom);
mImpl.updatePadding(this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!(mImpl instanceof CardViewApi21)) {
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
switch (widthMode) {
case MeasureSpec.EXACTLY:
case MeasureSpec.AT_MOST:
final int minWidth = (int) Math.ceil(mImpl.getMinWidth(this));
widthMeasureSpec = MeasureSpec.makeMeasureSpec(Math.max(minWidth,
MeasureSpec.getSize(widthMeasureSpec)), widthMode);
break;
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
switch (heightMode) {
case MeasureSpec.EXACTLY:
case MeasureSpec.AT_MOST:
final int minHeight = (int) Math.ceil(mImpl.getMinHeight(this));
heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.max(minHeight,
MeasureSpec.getSize(heightMeasureSpec)), heightMode);
break;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
private void initialize(Context context, AttributeSet attrs, int defStyleAttr) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CardView, defStyleAttr, R.style.CardView_Light);
boolean forceNoElevation = a.getBoolean(R.styleable.CardView_forceNoElevation, false);
if (forceNoElevation) {
mImpl = NO_ELEVATION_IMPL;
} else {
mImpl = IMPL;
}
int backgroundColor = a.getColor(R.styleable.CardView_cardBackgroundColor, 0);
float radius = a.getDimension(R.styleable.CardView_cardCornerRadius, 0);
float elevation = a.getDimension(R.styleable.CardView_cardElevation, 0);
float maxElevation = a.getDimension(R.styleable.CardView_cardMaxElevation, 0);
mCompatPadding = a.getBoolean(R.styleable.CardView_cardUseCompatPadding, false);
mPreventCornerOverlap = a.getBoolean(R.styleable.CardView_cardPreventCornerOverlap, true);
int defaultPadding = a.getDimensionPixelSize(R.styleable.CardView_contentPadding, 0);
mContentPadding.left = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingLeft,
defaultPadding);
mContentPadding.top = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingTop,
defaultPadding);
mContentPadding.right = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingRight,
defaultPadding);
mContentPadding.bottom = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingBottom,
defaultPadding);
if (elevation > maxElevation) {
maxElevation = elevation;
}
a.recycle();
mImpl.initialize(this, context, backgroundColor, radius, elevation, maxElevation);
}
/**
* Updates the background color of the CardView
*
* @param color The new color to set for the card background
* @attr ref android.support.v7.cardview.R.styleable#CardView_cardBackgroundColor
*/
public void setCardBackgroundColor(int color) {
mImpl.setBackgroundColor(this, color);
}
/**
* Returns the inner padding after the Card's left edge
*
* @return the inner padding after the Card's left edge
*/
public int getContentPaddingLeft() {
return mContentPadding.left;
}
/**
* Returns the inner padding before the Card's right edge
*
* @return the inner padding before the Card's right edge
*/
public int getContentPaddingRight() {
return mContentPadding.right;
}
/**
* Returns the inner padding after the Card's top edge
*
* @return the inner padding after the Card's top edge
*/
public int getContentPaddingTop() {
return mContentPadding.top;
}
/**
* Returns the inner padding before the Card's bottom edge
*
* @return the inner padding before the Card's bottom edge
*/
public int getContentPaddingBottom() {
return mContentPadding.bottom;
}
/**
* Updates the corner radius of the CardView.
*
* @param radius The radius in pixels of the corners of the rectangle shape
* @attr ref android.support.v7.cardview.R.styleable#CardView_cardCornerRadius
* @see #setRadius(float)
*/
public void setRadius(float radius) {
mImpl.setRadius(this, radius);
}
/**
* Returns the corner radius of the CardView.
*
* @return Corner radius of the CardView
* @see #getRadius()
*/
@Override
public float getRadius() {
return mImpl.getRadius(this);
}
/**
* Internal method used by CardView implementations to update the padding.
*
* @hide
*/
@Override
public void setShadowPadding(int left, int top, int right, int bottom) {
mShadowBounds.set(left, top, right, bottom);
super.setPadding(left + mContentPadding.left, top + mContentPadding.top,
right + mContentPadding.right, bottom + mContentPadding.bottom);
}
/**
* Updates the backward compatible elevation of the CardView.
*
* @param radius The backward compatible elevation in pixels.
* @attr ref android.support.v7.cardview.R.styleable#CardView_cardElevation
* @see #getCardElevation()
* @see #setMaxCardElevation(float)
*/
public void setCardElevation(float radius) {
mImpl.setElevation(this, radius);
}
/**
* Returns the backward compatible elevation of the CardView.
*
* @return Elevation of the CardView
* @see #setCardElevation(float)
* @see #getMaxCardElevation()
*/
public float getCardElevation() {
return mImpl.getElevation(this);
}
/**
* Updates the backward compatible elevation of the CardView.
* <p>
* Calling this method has no effect if device OS version is L or newer and
* {@link #getUseCompatPadding()} is <code>false</code>.
*
* @param radius The backward compatible elevation in pixels.
* @attr ref android.support.v7.cardview.R.styleable#CardView_cardElevation
* @see #setCardElevation(float)
* @see #getMaxCardElevation()
*/
public void setMaxCardElevation(float radius) {
mImpl.setMaxElevation(this, radius);
}
/**
* Returns the backward compatible elevation of the CardView.
*
* @return Elevation of the CardView
* @see #setMaxCardElevation(float)
* @see #getCardElevation()
*/
public float getMaxCardElevation() {
return mImpl.getMaxElevation(this);
}
/**
* Returns whether CardView should add extra padding to content to avoid overlaps with rounded
* corners on API versions 20 and below.
*
* @return True if CardView prevents overlaps with rounded corners on platforms before L.
* Default value is <code>true</code>.
*/
@Override
public boolean getPreventCornerOverlap() {
return mPreventCornerOverlap;
}
/**
* On API 20 and before, CardView does not clip the bounds of the Card for the rounded corners.
* Instead, it adds padding to content so that it won't overlap with the rounded corners.
* You can disable this behavior by setting this field to <code>false</code>.
* <p>
* Setting this value on API 21 and above does not have any effect unless you have enabled
* compatibility padding.
*
* @param preventCornerOverlap Whether CardView should add extra padding to content to avoid
* overlaps with the CardView corners.
* @attr ref android.support.v7.cardview.R.styleable#CardView_cardPreventCornerOverlap
* @see #setUseCompatPadding(boolean)
*/
public void setPreventCornerOverlap(boolean preventCornerOverlap) {
if (preventCornerOverlap == mPreventCornerOverlap) {
return;
}
mPreventCornerOverlap = preventCornerOverlap;
mImpl.onPreventCornerOverlapChanged(this);
}
}
@@ -0,0 +1,111 @@
/*
* Copyright (C) 2015 Hippo Seven
*
* 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
* 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.
*/
package android.support.v7.widget;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.view.View;
class CardViewApi21 implements CardViewImpl {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void initialize(CardViewDelegate cardView, Context context, int backgroundColor,
float radius, float elevation, float maxElevation) {
final RoundRectDrawable backgroundDrawable = new RoundRectDrawable(backgroundColor, radius);
cardView.setBackgroundDrawable(backgroundDrawable);
View view = (View) cardView;
view.setClipToOutline(true);
view.setElevation(elevation);
setMaxElevation(cardView, maxElevation);
}
@Override
public void setRadius(CardViewDelegate cardView, float radius) {
((RoundRectDrawable) (cardView.getBackground())).setRadius(radius);
}
@Override
public void initStatic() {
}
@Override
public void setMaxElevation(CardViewDelegate cardView, float maxElevation) {
((RoundRectDrawable) (cardView.getBackground())).setPadding(maxElevation,
cardView.getUseCompatPadding(), cardView.getPreventCornerOverlap());
updatePadding(cardView);
}
@Override
public float getMaxElevation(CardViewDelegate cardView) {
return ((RoundRectDrawable) (cardView.getBackground())).getPadding();
}
@Override
public float getMinWidth(CardViewDelegate cardView) {
return getRadius(cardView) * 2;
}
@Override
public float getMinHeight(CardViewDelegate cardView) {
return getRadius(cardView) * 2;
}
@Override
public float getRadius(CardViewDelegate cardView) {
return ((RoundRectDrawable) (cardView.getBackground())).getRadius();
}
@Override
public void setElevation(CardViewDelegate cardView, float elevation) {
((View) cardView).setElevation(elevation);
}
@Override
public float getElevation(CardViewDelegate cardView) {
return ((View) cardView).getElevation();
}
@Override
public void updatePadding(CardViewDelegate cardView) {
if (!cardView.getUseCompatPadding()) {
cardView.setShadowPadding(0, 0, 0, 0);
return;
}
float elevation = getMaxElevation(cardView);
final float radius = getRadius(cardView);
int hPadding = (int) Math.ceil(RoundRectDrawableWithShadow
.calculateHorizontalPadding(elevation, radius, cardView.getPreventCornerOverlap()));
int vPadding = (int) Math.ceil(RoundRectDrawableWithShadow
.calculateVerticalPadding(elevation, radius, cardView.getPreventCornerOverlap()));
cardView.setShadowPadding(hPadding, vPadding, hPadding, vPadding);
}
@Override
public void onCompatPaddingChanged(CardViewDelegate cardView) {
setMaxElevation(cardView, getMaxElevation(cardView));
}
@Override
public void onPreventCornerOverlapChanged(CardViewDelegate cardView) {
setMaxElevation(cardView, getMaxElevation(cardView));
}
@Override
public void setBackgroundColor(CardViewDelegate cardView, int color) {
((RoundRectDrawable) (cardView.getBackground())).setColor(color);
}
}
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2015 Hippo Seven
*
* 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
* 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.
*/
package android.support.v7.widget;
import android.graphics.drawable.Drawable;
/**
* Interface provided by CardView to implementations.
* <p>
* Necessary to resolve circular dependency between base CardView and platform implementations.
*/
interface CardViewDelegate {
void setBackgroundDrawable(Drawable paramDrawable);
Drawable getBackground();
boolean getUseCompatPadding();
boolean getPreventCornerOverlap();
float getRadius();
void setShadowPadding(int left, int top, int right, int bottom);
}
@@ -0,0 +1,161 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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.
*/
package android.support.v7.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.View;
class CardViewEclairMr1 implements CardViewImpl {
final RectF sCornerRect = new RectF();
@Override
public void initStatic() {
// Draws a round rect using 7 draw operations. This is faster than using
// canvas.drawRoundRect before JBMR1 because API 11-16 used alpha mask textures to draw
// shapes.
RoundRectDrawableWithShadow.sRoundRectHelper
= new RoundRectDrawableWithShadow.RoundRectHelper() {
@Override
public void drawRoundRect(Canvas canvas, RectF bounds, float cornerRadius,
Paint paint) {
final float twoRadius = cornerRadius * 2;
final float innerWidth = bounds.width() - twoRadius - 1;
final float innerHeight = bounds.height() - twoRadius - 1;
// increment it to account for half pixels.
if (cornerRadius >= 1f) {
cornerRadius += .5f;
sCornerRect.set(-cornerRadius, -cornerRadius, cornerRadius, cornerRadius);
int saved = canvas.save();
canvas.translate(bounds.left + cornerRadius, bounds.top + cornerRadius);
canvas.drawArc(sCornerRect, 180, 90, true, paint);
canvas.translate(innerWidth, 0);
canvas.rotate(90);
canvas.drawArc(sCornerRect, 180, 90, true, paint);
canvas.translate(innerHeight, 0);
canvas.rotate(90);
canvas.drawArc(sCornerRect, 180, 90, true, paint);
canvas.translate(innerWidth, 0);
canvas.rotate(90);
canvas.drawArc(sCornerRect, 180, 90, true, paint);
canvas.restoreToCount(saved);
//draw top and bottom pieces
canvas.drawRect(bounds.left + cornerRadius - 1f, bounds.top,
bounds.right - cornerRadius + 1f, bounds.top + cornerRadius,
paint);
canvas.drawRect(bounds.left + cornerRadius - 1f,
bounds.bottom - cornerRadius + 1f, bounds.right - cornerRadius + 1f,
bounds.bottom, paint);
}
//// center
canvas.drawRect(bounds.left, bounds.top + Math.max(0, cornerRadius - 1f),
bounds.right, bounds.bottom - cornerRadius + 1f, paint);
}
};
}
@Override
public void initialize(CardViewDelegate cardView, Context context, int backgroundColor,
float radius, float elevation, float maxElevation) {
RoundRectDrawableWithShadow background = createBackground(context, backgroundColor, radius,
elevation, maxElevation);
background.setAddPaddingForCorners(cardView.getPreventCornerOverlap());
cardView.setBackgroundDrawable(background);
updatePadding(cardView);
}
RoundRectDrawableWithShadow createBackground(Context context, int backgroundColor,
float radius, float elevation, float maxElevation) {
return new RoundRectDrawableWithShadow(context.getResources(), backgroundColor, radius,
elevation, maxElevation);
}
@Override
public void updatePadding(CardViewDelegate cardView) {
Rect shadowPadding = new Rect();
getShadowBackground(cardView).getMaxShadowAndCornerPadding(shadowPadding);
((View) cardView).setMinimumHeight((int) Math.ceil(getMinHeight(cardView)));
((View) cardView).setMinimumWidth((int) Math.ceil(getMinWidth(cardView)));
cardView.setShadowPadding(shadowPadding.left, shadowPadding.top,
shadowPadding.right, shadowPadding.bottom);
}
@Override
public void onCompatPaddingChanged(CardViewDelegate cardView) {
// NO OP
}
@Override
public void onPreventCornerOverlapChanged(CardViewDelegate cardView) {
getShadowBackground(cardView).setAddPaddingForCorners(cardView.getPreventCornerOverlap());
updatePadding(cardView);
}
@Override
public void setBackgroundColor(CardViewDelegate cardView, int color) {
getShadowBackground(cardView).setColor(color);
}
@Override
public void setRadius(CardViewDelegate cardView, float radius) {
getShadowBackground(cardView).setCornerRadius(radius);
updatePadding(cardView);
}
@Override
public float getRadius(CardViewDelegate cardView) {
return getShadowBackground(cardView).getCornerRadius();
}
@Override
public void setElevation(CardViewDelegate cardView, float elevation) {
getShadowBackground(cardView).setShadowSize(elevation);
}
@Override
public float getElevation(CardViewDelegate cardView) {
return getShadowBackground(cardView).getShadowSize();
}
@Override
public void setMaxElevation(CardViewDelegate cardView, float maxElevation) {
getShadowBackground(cardView).setMaxShadowSize(maxElevation);
updatePadding(cardView);
}
@Override
public float getMaxElevation(CardViewDelegate cardView) {
return getShadowBackground(cardView).getMaxShadowSize();
}
@Override
public float getMinWidth(CardViewDelegate cardView) {
return getShadowBackground(cardView).getMinWidth();
}
@Override
public float getMinHeight(CardViewDelegate cardView) {
return getShadowBackground(cardView).getMinHeight();
}
private RoundRectDrawableWithShadow getShadowBackground(CardViewDelegate cardView) {
return ((RoundRectDrawableWithShadow) cardView.getBackground());
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2015 Hippo Seven
*
* 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
* 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.
*/
package android.support.v7.widget;
import android.content.Context;
/**
* Interface for platform specific CardView implementations.
*/
interface CardViewImpl {
void initialize(CardViewDelegate cardView, Context context, int backgroundColor, float radius, float elevation, float maxElevation);
void setRadius(CardViewDelegate cardView, float radius);
float getRadius(CardViewDelegate cardView);
void setElevation(CardViewDelegate cardView, float elevation);
float getElevation(CardViewDelegate cardView);
void initStatic();
void setMaxElevation(CardViewDelegate cardView, float maxElevation);
float getMaxElevation(CardViewDelegate cardView);
float getMinWidth(CardViewDelegate cardView);
float getMinHeight(CardViewDelegate cardView);
void updatePadding(CardViewDelegate cardView);
void onCompatPaddingChanged(CardViewDelegate cardView);
void onPreventCornerOverlapChanged(CardViewDelegate cardView);
void setBackgroundColor(CardViewDelegate cardView, int color);
}
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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.
*/
package android.support.v7.widget;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
class CardViewJellybeanMr1 extends CardViewEclairMr1 {
@Override
public void initStatic() {
RoundRectDrawableWithShadow.sRoundRectHelper
= new RoundRectDrawableWithShadow.RoundRectHelper() {
@Override
public void drawRoundRect(Canvas canvas, RectF bounds, float cornerRadius,
Paint paint) {
canvas.drawRoundRect(bounds, cornerRadius, cornerRadius, paint);
}
};
}
}
@@ -0,0 +1,132 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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.
*/
package android.support.v7.widget;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import static android.support.v7.widget.RoundRectDrawableWithShadow.calculateVerticalPadding;
import static android.support.v7.widget.RoundRectDrawableWithShadow.calculateHorizontalPadding;
/**
* Very simple drawable that draws a rounded rectangle background with arbitrary corners and also
* reports proper outline for L.
* <p>
* Simpler and uses less resources compared to GradientDrawable or ShapeDrawable.
*/
class RoundRectDrawable extends Drawable {
private float mRadius;
private final Paint mPaint;
private final RectF mBoundsF;
private final Rect mBoundsI;
private float mPadding;
private boolean mInsetForPadding = false;
private boolean mInsetForRadius = true;
public RoundRectDrawable(int backgroundColor, float radius) {
mRadius = radius;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaint.setColor(backgroundColor);
mBoundsF = new RectF();
mBoundsI = new Rect();
}
void setPadding(float padding, boolean insetForPadding, boolean insetForRadius) {
if (padding == mPadding && mInsetForPadding == insetForPadding &&
mInsetForRadius == insetForRadius) {
return;
}
mPadding = padding;
mInsetForPadding = insetForPadding;
mInsetForRadius = insetForRadius;
updateBounds(null);
invalidateSelf();
}
float getPadding() {
return mPadding;
}
@Override
public void draw(Canvas canvas) {
canvas.drawRoundRect(mBoundsF, mRadius, mRadius, mPaint);
}
private void updateBounds(Rect bounds) {
if (bounds == null) {
bounds = getBounds();
}
mBoundsF.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
mBoundsI.set(bounds);
if (mInsetForPadding) {
float vInset = calculateVerticalPadding(mPadding, mRadius, mInsetForRadius);
float hInset = calculateHorizontalPadding(mPadding, mRadius, mInsetForRadius);
mBoundsI.inset((int) Math.ceil(hInset), (int) Math.ceil(vInset));
// to make sure they have same bounds.
mBoundsF.set(mBoundsI);
}
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
updateBounds(bounds);
}
@Override
public void getOutline(Outline outline) {
outline.setRoundRect(mBoundsI, mRadius);
}
void setRadius(float radius) {
if (radius == mRadius) {
return;
}
mRadius = radius;
updateBounds(null);
invalidateSelf();
}
@Override
public void setAlpha(int alpha) {
// not supported because older versions do not support
}
@Override
public void setColorFilter(ColorFilter cf) {
// not supported because older versions do not support
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
public float getRadius() {
return mRadius;
}
public void setColor(int color) {
mPaint.setColor(color);
invalidateSelf();
}
}
@@ -0,0 +1,354 @@
/*
* Copyright (C) 2015 Hippo Seven
*
* 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
* 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.
*/
package android.support.v7.widget;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import com.hippo.ehviewer.R;
/**
* A rounded rectangle drawable which also includes a shadow around.
*/
class RoundRectDrawableWithShadow extends Drawable {
// used to calculate content padding
final static double COS_45 = Math.cos(Math.toRadians(45));
final static float SHADOW_MULTIPLIER = 1.5f;
final int mInsetShadow; // extra shadow to avoid gaps between card and shadow
/*
* This helper is set by CardView implementations.
* <p>
* Prior to API 17, canvas.drawRoundRect is expensive; which is why we need this interface
* to draw efficient rounded rectangles before 17.
* */
static RoundRectHelper sRoundRectHelper;
Paint mPaint;
Paint mCornerShadowPaint;
Paint mEdgeShadowPaint;
final RectF mCardBounds;
float mCornerRadius;
Path mCornerShadowPath;
// updated value with inset
float mMaxShadowSize;
// actual value set by developer
float mRawMaxShadowSize;
// multiplied value to account for shadow offset
float mShadowSize;
// actual value set by developer
float mRawShadowSize;
private boolean mDirty = true;
private final int mShadowStartColor;
private final int mShadowEndColor;
private boolean mAddPaddingForCorners = true;
/**
* If shadow size is set to a value above max shadow, we print a warning
*/
private boolean mPrintedShadowClipWarning = false;
RoundRectDrawableWithShadow(Resources resources, int backgroundColor, float radius,
float shadowSize, float maxShadowSize) {
mShadowStartColor = resources.getColor(R.color.cardview_shadow_start_color);
mShadowEndColor = resources.getColor(R.color.cardview_shadow_end_color);
mInsetShadow = resources.getDimensionPixelSize(R.dimen.cardview_compat_inset_shadow);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaint.setColor(backgroundColor);
mCornerShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mCornerShadowPaint.setStyle(Paint.Style.FILL);
mCornerRadius = (int) (radius + .5f);
mCardBounds = new RectF();
mEdgeShadowPaint = new Paint(mCornerShadowPaint);
mEdgeShadowPaint.setAntiAlias(false);
setShadowSize(shadowSize, maxShadowSize);
}
/**
* Casts the value to an even integer.
*/
private int toEven(float value) {
int i = (int) (value + .5f);
if (i % 2 == 1) {
return i - 1;
}
return i;
}
public void setAddPaddingForCorners(boolean addPaddingForCorners) {
mAddPaddingForCorners = addPaddingForCorners;
invalidateSelf();
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
mCornerShadowPaint.setAlpha(alpha);
mEdgeShadowPaint.setAlpha(alpha);
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mDirty = true;
}
void setShadowSize(float shadowSize, float maxShadowSize) {
if (shadowSize < 0 || maxShadowSize < 0) {
throw new IllegalArgumentException("invalid shadow size");
}
shadowSize = toEven(shadowSize);
maxShadowSize = toEven(maxShadowSize);
if (shadowSize > maxShadowSize) {
shadowSize = maxShadowSize;
if (!mPrintedShadowClipWarning) {
mPrintedShadowClipWarning = true;
}
}
if (mRawShadowSize == shadowSize && mRawMaxShadowSize == maxShadowSize) {
return;
}
mRawShadowSize = shadowSize;
mRawMaxShadowSize = maxShadowSize;
mShadowSize = (int)(shadowSize * SHADOW_MULTIPLIER + mInsetShadow + .5f);
mMaxShadowSize = maxShadowSize + mInsetShadow;
mDirty = true;
invalidateSelf();
}
@Override
public boolean getPadding(Rect padding) {
int vOffset = (int) Math.ceil(calculateVerticalPadding(mRawMaxShadowSize, mCornerRadius,
mAddPaddingForCorners));
int hOffset = (int) Math.ceil(calculateHorizontalPadding(mRawMaxShadowSize, mCornerRadius,
mAddPaddingForCorners));
padding.set(hOffset, vOffset, hOffset, vOffset);
return true;
}
static float calculateVerticalPadding(float maxShadowSize, float cornerRadius,
boolean addPaddingForCorners) {
if (addPaddingForCorners) {
return (float) (maxShadowSize * SHADOW_MULTIPLIER + (1 - COS_45) * cornerRadius);
} else {
return maxShadowSize * SHADOW_MULTIPLIER;
}
}
static float calculateHorizontalPadding(float maxShadowSize, float cornerRadius,
boolean addPaddingForCorners) {
if (addPaddingForCorners) {
return (float) (maxShadowSize + (1 - COS_45) * cornerRadius);
} else {
return maxShadowSize;
}
}
@Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
mCornerShadowPaint.setColorFilter(cf);
mEdgeShadowPaint.setColorFilter(cf);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
void setCornerRadius(float radius) {
radius = (int) (radius + .5f);
if (mCornerRadius == radius) {
return;
}
mCornerRadius = radius;
mDirty = true;
invalidateSelf();
}
@Override
public void draw(Canvas canvas) {
if (mDirty) {
buildComponents(getBounds());
mDirty = false;
}
canvas.translate(0, mRawShadowSize / 2);
drawShadow(canvas);
canvas.translate(0, -mRawShadowSize / 2);
sRoundRectHelper.drawRoundRect(canvas, mCardBounds, mCornerRadius, mPaint);
}
private void drawShadow(Canvas canvas) {
final float edgeShadowTop = -mCornerRadius - mShadowSize;
final float inset = mCornerRadius + mInsetShadow + mRawShadowSize / 2;
final boolean drawHorizontalEdges = mCardBounds.width() - 2 * inset > 0;
final boolean drawVerticalEdges = mCardBounds.height() - 2 * inset > 0;
// LT
int saved = canvas.save();
canvas.translate(mCardBounds.left + inset, mCardBounds.top + inset);
canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
if (drawHorizontalEdges) {
canvas.drawRect(0, edgeShadowTop,
mCardBounds.width() - 2 * inset, -mCornerRadius,
mEdgeShadowPaint);
}
canvas.restoreToCount(saved);
// RB
saved = canvas.save();
canvas.translate(mCardBounds.right - inset, mCardBounds.bottom - inset);
canvas.rotate(180f);
canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
if (drawHorizontalEdges) {
canvas.drawRect(0, edgeShadowTop,
mCardBounds.width() - 2 * inset, -mCornerRadius + mShadowSize,
mEdgeShadowPaint);
}
canvas.restoreToCount(saved);
// LB
saved = canvas.save();
canvas.translate(mCardBounds.left + inset, mCardBounds.bottom - inset);
canvas.rotate(270f);
canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
if (drawVerticalEdges) {
canvas.drawRect(0, edgeShadowTop,
mCardBounds.height() - 2 * inset, -mCornerRadius, mEdgeShadowPaint);
}
canvas.restoreToCount(saved);
// RT
saved = canvas.save();
canvas.translate(mCardBounds.right - inset, mCardBounds.top + inset);
canvas.rotate(90f);
canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
if (drawVerticalEdges) {
canvas.drawRect(0, edgeShadowTop,
mCardBounds.height() - 2 * inset, -mCornerRadius, mEdgeShadowPaint);
}
canvas.restoreToCount(saved);
}
private void buildShadowCorners() {
RectF innerBounds = new RectF(-mCornerRadius, -mCornerRadius, mCornerRadius, mCornerRadius);
RectF outerBounds = new RectF(innerBounds);
outerBounds.inset(-mShadowSize, -mShadowSize);
if (mCornerShadowPath == null) {
mCornerShadowPath = new Path();
} else {
mCornerShadowPath.reset();
}
mCornerShadowPath.setFillType(Path.FillType.EVEN_ODD);
mCornerShadowPath.moveTo(-mCornerRadius, 0);
mCornerShadowPath.rLineTo(-mShadowSize, 0);
// outer arc
mCornerShadowPath.arcTo(outerBounds, 180f, 90f, false);
// inner arc
mCornerShadowPath.arcTo(innerBounds, 270f, -90f, false);
mCornerShadowPath.close();
float startRatio = mCornerRadius / (mCornerRadius + mShadowSize);
mCornerShadowPaint.setShader(new RadialGradient(0, 0, mCornerRadius + mShadowSize,
new int[]{mShadowStartColor, mShadowStartColor, mShadowEndColor},
new float[]{0f, startRatio, 1f}
, Shader.TileMode.CLAMP));
// we offset the content shadowSize/2 pixels up to make it more realistic.
// this is why edge shadow shader has some extra space
// When drawing bottom edge shadow, we use that extra space.
mEdgeShadowPaint.setShader(new LinearGradient(0, -mCornerRadius + mShadowSize, 0,
-mCornerRadius - mShadowSize,
new int[]{mShadowStartColor, mShadowStartColor, mShadowEndColor},
new float[]{0f, .5f, 1f}, Shader.TileMode.CLAMP));
mEdgeShadowPaint.setAntiAlias(false);
}
private void buildComponents(Rect bounds) {
// Card is offset SHADOW_MULTIPLIER * maxShadowSize to account for the shadow shift.
// We could have different top-bottom offsets to avoid extra gap above but in that case
// center aligning Views inside the CardView would be problematic.
final float verticalOffset = mRawMaxShadowSize * SHADOW_MULTIPLIER;
mCardBounds.set(bounds.left + mRawMaxShadowSize, bounds.top + verticalOffset,
bounds.right - mRawMaxShadowSize, bounds.bottom - verticalOffset);
buildShadowCorners();
}
float getCornerRadius() {
return mCornerRadius;
}
void getMaxShadowAndCornerPadding(Rect into) {
getPadding(into);
}
void setShadowSize(float size) {
setShadowSize(size, mRawMaxShadowSize);
}
void setMaxShadowSize(float size) {
setShadowSize(mRawShadowSize, size);
}
float getShadowSize() {
return mRawShadowSize;
}
float getMaxShadowSize() {
return mRawMaxShadowSize;
}
float getMinWidth() {
final float content = 2 *
Math.max(mRawMaxShadowSize, mCornerRadius + mInsetShadow + mRawMaxShadowSize / 2);
return content + (mRawMaxShadowSize + mInsetShadow) * 2;
}
float getMinHeight() {
final float content = 2 * Math.max(mRawMaxShadowSize, mCornerRadius + mInsetShadow
+ mRawMaxShadowSize * SHADOW_MULTIPLIER / 2);
return content + (mRawMaxShadowSize * SHADOW_MULTIPLIER + mInsetShadow) * 2;
}
public void setColor(int color) {
mPaint.setColor(color);
invalidateSelf();
}
static interface RoundRectHelper {
void drawRoundRect(Canvas canvas, RectF bounds, float cornerRadius, Paint paint);
}
}
@@ -15,10 +15,15 @@
package com.hippo.ehviewer.widget;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Path;
import android.graphics.Typeface;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v7.widget.CardView;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -27,31 +32,50 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.hippo.animation.SimpleAnimatorListener;
import com.hippo.drawable.AddDeleteDrawable;
import com.hippo.drawable.DrawerArrowDrawable;
import com.hippo.ehviewer.R;
import com.hippo.util.MathUtils;
import com.hippo.util.UiUtils;
import com.hippo.util.ViewUtils;
import com.hippo.widget.SimpleImageView;
import java.util.ArrayList;
import java.util.List;
public class SearchBar extends CardView implements View.OnClickListener,
TextView.OnEditorActionListener {
private static final long ANIMATION_TIME = 300;
private Path mPath = new Path();
private int mWidth;
private int mHeight;
private int mBaseHeight;
private float mProgress;
private SimpleImageView mMenuButton;
private TextView mLogoTextView;
private SimpleImageView mActionButton;
private SearchEditText mEditText;
private ListView mList;
private DrawerArrowDrawable mDrawerArrowDrawable;
private AddDeleteDrawable mAddDeleteDrawable;
private List<String> mSuggestionList;
private ArrayAdapter mSuggestionAdapter;
private Helper mHelper;
private boolean mInEditMode = false;
private boolean mInAnimation = false;
private boolean mFirstLayout = true;
public SearchBar(Context context) {
super(context);
@@ -71,6 +95,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
private void init(Context context) {
setRadius(UiUtils.dp2pix(context, 2));
setCardElevation(UiUtils.dp2pix(context, 2));
setCardBackgroundColor(Color.WHITE);
setOnClickListener(this);
LayoutInflater.from(context).inflate(R.layout.widget_search_bar, this);
@@ -78,6 +103,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
mLogoTextView = (TextView) findViewById(R.id.logo);
mActionButton = (SimpleImageView) findViewById(R.id.action);
mEditText = (SearchEditText) findViewById(R.id.search_edit_text);
mList = (ListView) findViewById(R.id.search_bar_list);
mDrawerArrowDrawable = new DrawerArrowDrawable(getContext());
mAddDeleteDrawable = new AddDeleteDrawable(getContext());
@@ -89,6 +115,15 @@ public class SearchBar extends CardView implements View.OnClickListener,
mActionButton.setOnClickListener(this);
mEditText.setSearchBar(this);
mEditText.setOnEditorActionListener(this);
mSuggestionList = new ArrayList<>();
mSuggestionList.add("aaaaaaaaaaaaaaaaaaaaa");
mSuggestionList.add("dfsgfewrewfes");
mSuggestionList.add("dehyklrthrhbdsrf");
mSuggestionList.add("粉色热污染份额为别人的");
mSuggestionAdapter = new ArrayAdapter<>(getContext(),
android.R.layout.simple_list_item_1, mSuggestionList);
mList.setAdapter(mSuggestionAdapter);
}
public void setHelper(Helper helper) {
@@ -144,12 +179,28 @@ public class SearchBar extends CardView implements View.OnClickListener,
oa1.setDuration(ANIMATION_TIME);
ObjectAnimator oa2 = ObjectAnimator.ofFloat(mAddDeleteDrawable, "progress", 0f, 1f);
oa2.setDuration(ANIMATION_TIME);
ObjectAnimator oa3 = ObjectAnimator.ofFloat(this, "progress", 0f, 1f);
oa3.setDuration(ANIMATION_TIME);
oa3.addListener(new SimpleAnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
ViewUtils.setVisibility(mList, View.VISIBLE);
mInAnimation = true;
}
@Override
public void onAnimationEnd(Animator animation) {
mInAnimation = false;
}
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
oa1.setAutoCancel(true);
oa2.setAutoCancel(true);
oa3.setAutoCancel(true);
}
oa1.start();
oa2.start();
oa3.start();
}
}
@@ -167,12 +218,67 @@ public class SearchBar extends CardView implements View.OnClickListener,
oa1.setDuration(ANIMATION_TIME);
ObjectAnimator oa2 = ObjectAnimator.ofFloat(mAddDeleteDrawable, "progress", 1f, 0f);
oa2.setDuration(ANIMATION_TIME);
ObjectAnimator oa3 = ObjectAnimator.ofFloat(this, "progress", 1f, 0f);
oa3.setDuration(ANIMATION_TIME);
oa3.addListener(new SimpleAnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
mInAnimation = true;
}
@Override
public void onAnimationEnd(Animator animation) {
ViewUtils.setVisibility(mList, View.GONE);
mInAnimation = false;
}
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
oa1.setAutoCancel(true);
oa2.setAutoCancel(true);
oa3.setAutoCancel(true);
}
oa1.start();
oa2.start();
oa3.start();
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mInEditMode) {
mWidth = right - left;
mHeight = bottom - top;
}
if (mFirstLayout) {
mFirstLayout = false;
mBaseHeight = bottom - top;
}
}
@SuppressWarnings("unused")
public void setProgress(float progress) {
mProgress = progress;
invalidate();
}
@SuppressWarnings("unused")
public float getProgress() {
return mProgress;
}
@Override
public void draw(@NonNull Canvas canvas) {
if (mInAnimation) {
final int state = canvas.save();
float bottom = MathUtils.lerp(mBaseHeight, mHeight, mProgress);
mPath.rewind();
mPath.addRect(0f, 0f, mWidth, bottom, Path.Direction.CW);
canvas.clipPath(mPath);
super.draw(canvas);
canvas.restoreToCount(state);
} else {
super.draw(canvas);
}
}
@@ -18,17 +18,19 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.hippo.ehviewer.widget.SearchBar
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_margin="8dp"/>
<com.hippo.ehviewer.widget.ContentLayout
android:id="@+id/content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
<com.hippo.ehviewer.widget.SearchBar
xmlns:auto="http://schemas.android.com/apk/res-auto"
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
auto:forceNoElevation="true"/>
</FrameLayout>
@@ -19,7 +19,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
@@ -69,8 +69,10 @@
</FrameLayout>
<ListView
android:id="@+id/search_bar_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content"
android:visibility="gone"/>
</LinearLayout>
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2015 Hippo Seven
~
~ 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
~ 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.
-->
<resources>
<declare-styleable name="CardView">
<!-- Background color for CardView. -->
<attr name="cardBackgroundColor" format="color" />
<!-- Corner radius for CardView. -->
<attr name="cardCornerRadius" format="dimension" />
<!-- Elevation for CardView. -->
<attr name="cardElevation" format="dimension" />
<!-- Maximum Elevation for CardView. -->
<attr name="cardMaxElevation" format="dimension" />
<!-- Add padding in API v21+ as well to have the same measurements with previous versions. -->
<attr name="cardUseCompatPadding" format="boolean" />
<!-- Add padding to CardView on v20 and before to prevent intersections between the Card content and rounded corners. -->
<attr name="cardPreventCornerOverlap" format="boolean" />
<!-- Inner padding between the edges of the Card and children of the CardView. -->
<attr name="contentPadding" format="dimension" />
<!-- Inner padding between the left edge of the Card and children of the CardView. -->
<attr name="contentPaddingLeft" format="dimension" />
<!-- Inner padding between the right edge of the Card and children of the CardView. -->
<attr name="contentPaddingRight" format="dimension" />
<!-- Inner padding between the top edge of the Card and children of the CardView. -->
<attr name="contentPaddingTop" format="dimension" />
<!-- Inner padding between the bottom edge of the Card and children of the CardView. -->
<attr name="contentPaddingBottom" format="dimension" />
<!-- -->
<attr name="forceNoElevation" format="boolean" />
</declare-styleable>
</resources>
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
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.
-->
<resources>
<!-- Background color for light CardView. -->
<color name="cardview_light_background">#FFFAFAFA</color>
<!-- Background color for dark CardView. -->
<color name="cardview_dark_background">#FF202020</color>
<!-- Shadow color for the first pixels around CardView. -->
<color name="cardview_shadow_start_color">#37000000</color>
<!-- Shadow color for the furthest pixels around CardView. -->
<color name="cardview_shadow_end_color">#03000000</color>
</resources>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
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.
-->
<resources>
<!-- Default radius for CardView corners. -->
<dimen name="cardview_default_radius">2dp</dimen>
<!-- Elevation value to use for CardViews. Pre-L, it is equal to shadow size. -->
<dimen name="cardview_default_elevation">2dp</dimen>
<!-- Inset shadow for RoundRectDrawableWithShadow. It is used to avoid gaps between the card
and the shadow. -->
<dimen name="cardview_compat_inset_shadow">1dp</dimen>
</resources>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
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.
-->
<resources>
<style name="CardView">
<item name="cardBackgroundColor">@color/cardview_light_background</item>
<item name="cardCornerRadius">@dimen/cardview_default_radius</item>
<item name="cardElevation">@dimen/cardview_default_elevation</item>
<item name="cardMaxElevation">@dimen/cardview_default_elevation</item>
<item name="cardUseCompatPadding">false</item>
<item name="cardPreventCornerOverlap">true</item>
</style>
<style name="CardView.Light">
<item name="cardBackgroundColor">@color/cardview_light_background</item>
</style>
<style name="CardView.Dark">
<item name="cardBackgroundColor">@color/cardview_dark_background</item>
</style>
</resources>