mirror of
https://gitee.com/houstudio/Cdroid.git
synced 2024-12-04 21:27:41 +08:00
make drawables's getHotspotBounds const
This commit is contained in:
parent
2fa549abc3
commit
80c323be8c
@ -74,7 +74,7 @@ void Drawable::setHotspot(float x,float y) {
|
||||
void Drawable::setHotspotBounds(int left,int top,int width,int height) {
|
||||
}
|
||||
|
||||
void Drawable::getHotspotBounds(Rect&outRect) {
|
||||
void Drawable::getHotspotBounds(Rect&outRect)const{
|
||||
outRect = mBounds;
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ public:
|
||||
virtual int getOpacity();
|
||||
virtual void setHotspot(float x,float y);
|
||||
virtual void setHotspotBounds(int left,int top,int width,int height);
|
||||
virtual void getHotspotBounds(Rect&outRect);
|
||||
virtual void getHotspotBounds(Rect&outRect)const;
|
||||
virtual bool getPadding(Rect&padding);
|
||||
virtual Insets getOpticalInsets();
|
||||
virtual bool isStateful()const;
|
||||
|
@ -607,9 +607,9 @@ void DrawableContainer::setHotspotBounds(int left, int top, int width, int heigh
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableContainer::getHotspotBounds(Rect& outRect){
|
||||
void DrawableContainer::getHotspotBounds(Rect& outRect)const{
|
||||
if(mHotspotBounds.empty())outRect = mHotspotBounds;
|
||||
else Drawable::getHotspotBounds(mBounds);
|
||||
else Drawable::getHotspotBounds(outRect);
|
||||
}
|
||||
|
||||
int DrawableContainer::getCurrentIndex()const{
|
||||
|
@ -113,7 +113,7 @@ public:
|
||||
int getIntrinsicHeight()const override;
|
||||
int getMinimumWidth() const override;
|
||||
int getMinimumHeight()const override;
|
||||
void getHotspotBounds(Rect& outRect) override;
|
||||
void getHotspotBounds(Rect& outRect)const override;
|
||||
void setHotspotBounds(int left, int top, int width, int height)override;
|
||||
void setColorFilter(ColorFilter*colorFilter)override;
|
||||
void setTintList(const ColorStateList*tint)override;
|
||||
|
@ -124,7 +124,7 @@ int DrawableWrapper::getIntrinsicHeight()const {
|
||||
return mDrawable != nullptr ? mDrawable->getIntrinsicHeight() : -1;
|
||||
}
|
||||
|
||||
void DrawableWrapper::getHotspotBounds(Rect& outRect){
|
||||
void DrawableWrapper::getHotspotBounds(Rect& outRect)const{
|
||||
if(mDrawable)mDrawable->getHotspotBounds(outRect);
|
||||
else outRect = mBounds;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
int getIntrinsicWidth ()const override;
|
||||
int getIntrinsicHeight()const override;
|
||||
int getChangingConfigurations()const override;
|
||||
void getHotspotBounds(Rect& outRect) override;
|
||||
void getHotspotBounds(Rect& outRect)const override;
|
||||
void setDrawable(Drawable* dr);
|
||||
Drawable* getDrawable()const;
|
||||
DrawableWrapper*mutate()override;
|
||||
|
@ -575,7 +575,7 @@ void LayerDrawable::setHotspotBounds(int left,int top,int width,int height){
|
||||
mHotspotBounds.set(left, top, width,height);
|
||||
}
|
||||
|
||||
void LayerDrawable::getHotspotBounds(Rect& outRect){
|
||||
void LayerDrawable::getHotspotBounds(Rect& outRect)const{
|
||||
if (!mHotspotBounds.empty()) {
|
||||
outRect = mHotspotBounds;
|
||||
} else {
|
||||
|
@ -145,7 +145,7 @@ public:
|
||||
int getPaddingMode()const;
|
||||
void setHotspot(float x,float y)override;
|
||||
void setHotspotBounds(int left,int top,int width,int height)override;
|
||||
void getHotspotBounds(Rect& outRect)override;
|
||||
void getHotspotBounds(Rect& outRect)const override;
|
||||
void setTintList(const ColorStateList* tint)override;
|
||||
void setTintMode(int tintMode)override;
|
||||
bool setVisible(bool visible,bool restart)override;
|
||||
|
@ -59,6 +59,9 @@ RippleDrawable::RippleDrawable(std::shared_ptr<RippleState> state) {
|
||||
updateLocalState();
|
||||
}
|
||||
|
||||
RippleDrawable::RippleDrawable():RippleDrawable(std::make_shared<RippleState>(nullptr,this)){
|
||||
}
|
||||
|
||||
RippleDrawable::RippleDrawable(const ColorStateList* color,Drawable* content,Drawable* mask)
|
||||
:RippleDrawable(std::make_shared<RippleState>(nullptr,nullptr)){
|
||||
if(content)addLayer(content,{0},-1,0,0,0,0);
|
||||
@ -129,7 +132,7 @@ void RippleDrawable::setRippleActive(bool active){
|
||||
}
|
||||
|
||||
void RippleDrawable::setBackgroundActive(bool hovered, bool focused, bool pressed){
|
||||
if (mBackground == nullptr && (hovered || focused)) {
|
||||
if ((mBackground == nullptr) && (hovered || focused)) {
|
||||
mBackground = new RippleBackground(this, mHotspotBounds, isBounded());
|
||||
mBackground->setup(mState->mMaxRadius, mDensity);
|
||||
}
|
||||
@ -301,8 +304,8 @@ void RippleDrawable::setHotspotBounds(int left,int top,int w,int h){
|
||||
onHotspotBoundsChanged();
|
||||
}
|
||||
|
||||
void RippleDrawable::getHotspotBounds(Rect&out){
|
||||
out=mHotspotBounds;
|
||||
void RippleDrawable::getHotspotBounds(Rect&out)const{
|
||||
out = mHotspotBounds;
|
||||
}
|
||||
|
||||
void RippleDrawable::onHotspotBoundsChanged(){
|
||||
@ -408,7 +411,6 @@ void RippleDrawable::drawBackgroundAndRipples(Canvas& canvas) {
|
||||
if (mBackground && mBackground->isVisible()) {
|
||||
mBackground->draw(canvas, 1.f);
|
||||
}
|
||||
|
||||
for (auto ripple:mExitingRipples) {
|
||||
const int alpha = 0x80 * ripple->getOpacity();
|
||||
color = (color&0x00FFFFFF) | (alpha<<24);
|
||||
@ -423,6 +425,140 @@ void RippleDrawable::drawBackgroundAndRipples(Canvas& canvas) {
|
||||
|
||||
void RippleDrawable::drawMask(Canvas& canvas) {
|
||||
mMask->draw(canvas);
|
||||
|
||||
}
|
||||
|
||||
void RippleDrawable::drawSolid(Canvas& canvas){
|
||||
pruneRipples();
|
||||
|
||||
// Clip to the dirty bounds, which will be the drawable bounds if we
|
||||
// have a mask or content and the ripple bounds if we're projecting.
|
||||
Rect bounds = getDirtyBounds();
|
||||
canvas.save();
|
||||
if (isBounded()) {
|
||||
canvas.rectangle(bounds);
|
||||
canvas.clip();
|
||||
}
|
||||
|
||||
drawContent(canvas);
|
||||
drawBackgroundAndRipples(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void RippleDrawable::exitPatternedBackgroundAnimation() {
|
||||
mTargetBackgroundOpacity = 0;
|
||||
if (mBackgroundAnimation) mBackgroundAnimation->cancel();
|
||||
// after cancel
|
||||
mRunBackgroundAnimation = true;
|
||||
invalidateSelf(false);
|
||||
}
|
||||
|
||||
void RippleDrawable::startPatternedAnimation() {
|
||||
mAddRipple = true;
|
||||
invalidateSelf(false);
|
||||
}
|
||||
|
||||
void RippleDrawable::exitPatternedAnimation() {
|
||||
mExitingAnimation = true;
|
||||
invalidateSelf(false);
|
||||
}
|
||||
|
||||
void RippleDrawable::enterPatternedBackgroundAnimation(bool focused, bool hovered) {
|
||||
mBackgroundOpacity = 0;
|
||||
mTargetBackgroundOpacity = focused ? .6f : hovered ? .2f : 0.f;
|
||||
if (mBackgroundAnimation) mBackgroundAnimation->cancel();
|
||||
// after cancel
|
||||
mRunBackgroundAnimation = true;
|
||||
invalidateSelf(false);
|
||||
}
|
||||
|
||||
void RippleDrawable::startBackgroundAnimation() {
|
||||
mRunBackgroundAnimation = false;
|
||||
/*if (Looper.myLooper() == null) {
|
||||
Log.w(TAG, "Thread doesn't have a looper. Skipping animation.");
|
||||
return;
|
||||
}*/
|
||||
mBackgroundAnimation = ValueAnimator::ofFloat({mBackgroundOpacity, mTargetBackgroundOpacity});
|
||||
/*mBackgroundAnimation->setInterpolator(LINEAR_INTERPOLATOR);
|
||||
mBackgroundAnimation->setDuration(BACKGROUND_OPACITY_DURATION);
|
||||
mBackgroundAnimation.addUpdateListener(update -> {
|
||||
mBackgroundOpacity = (float) update.getAnimatedValue();
|
||||
invalidateSelf(false);
|
||||
});*/
|
||||
mBackgroundAnimation->start();
|
||||
}
|
||||
|
||||
void RippleDrawable::drawPatterned(Canvas& canvas) {
|
||||
#if 0
|
||||
Rect bounds = mHotspotBounds;
|
||||
canvas.save();//Canvas.CLIP_SAVE_FLAG);
|
||||
bool useCanvasProps = !mForceSoftware;
|
||||
if (isBounded()) {
|
||||
canvas.rectangle(getDirtyBounds());
|
||||
canvas.clip();
|
||||
}
|
||||
float x, y, cx, cy, w, h;
|
||||
bool addRipple = mAddRipple;
|
||||
cx = bounds.centerX();
|
||||
cy = bounds.centerY();
|
||||
bool shouldExit = mExitingAnimation;
|
||||
mExitingAnimation = false;
|
||||
mAddRipple = false;
|
||||
if (mRunningAnimations.size() > 0 && !addRipple) {
|
||||
// update paint when view is invalidated
|
||||
updateRipplePaint();
|
||||
}
|
||||
drawContent(canvas);
|
||||
drawPatternedBackground(canvas, cx, cy);
|
||||
if (addRipple && mRunningAnimations.size() <= MAX_RIPPLES) {
|
||||
if (mHasPending) {
|
||||
x = mPendingX;
|
||||
y = mPendingY;
|
||||
mHasPending = false;
|
||||
} else {
|
||||
x = bounds.exactCenterX();
|
||||
y = bounds.exactCenterY();
|
||||
}
|
||||
h = bounds.height();
|
||||
w = bounds.width();
|
||||
RippleAnimationSession.AnimationProperties<Float, Paint> properties =
|
||||
createAnimationProperties(x, y, cx, cy, w, h);
|
||||
mRunningAnimations.add(new RippleAnimationSession(properties, !useCanvasProps)
|
||||
.setOnAnimationUpdated(() -> invalidateSelf(false))
|
||||
.setOnSessionEnd(session -> {
|
||||
mRunningAnimations.remove(session);
|
||||
})
|
||||
.setForceSoftwareAnimation(!useCanvasProps)
|
||||
.enter(canvas));
|
||||
}
|
||||
if (shouldExit) {
|
||||
for (int i = 0; i < mRunningAnimations.size(); i++) {
|
||||
RippleAnimationSession s = mRunningAnimations.get(i);
|
||||
s.exit(canvas);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < mRunningAnimations.size(); i++) {
|
||||
RippleAnimationSession s = mRunningAnimations.get(i);
|
||||
if (!canvas.isHardwareAccelerated()) {
|
||||
Log.e(TAG, "The RippleDrawable.STYLE_PATTERNED animation is not supported for a "
|
||||
+ "non-hardware accelerated Canvas. Skipping animation.");
|
||||
break;
|
||||
} else if (useCanvasProps) {
|
||||
RippleAnimationSession.AnimationProperties<CanvasProperty<Float>,
|
||||
CanvasProperty<Paint>>
|
||||
p = s.getCanvasProperties();
|
||||
RecordingCanvas can = (RecordingCanvas) canvas;
|
||||
can.drawRipple(p.getX(), p.getY(), p.getMaxRadius(), p.getPaint(),
|
||||
p.getProgress(), p.getNoisePhase(), p.getColor(), p.getShader());
|
||||
} else {
|
||||
RippleAnimationSession.AnimationProperties<Float, Paint> p =
|
||||
s.getProperties();
|
||||
float radius = p.getMaxRadius();
|
||||
canvas.drawCircle(p.getX(), p.getY(), radius, p.getPaint());
|
||||
}
|
||||
}
|
||||
canvas.restoreToCount(saveCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
Rect RippleDrawable::getDirtyBounds() {
|
||||
|
@ -13,11 +13,15 @@ public:
|
||||
static constexpr int MASK_CONTENT = 1;
|
||||
static constexpr int MASK_EXPLICIT = 2;
|
||||
static constexpr int MAX_RIPPLES = 10;
|
||||
static constexpr int STYLE_SOLID = 0;
|
||||
static constexpr int STYLE_PATTERNED = 1;
|
||||
static constexpr bool FORCE_PATTERNED_STYLE = true;
|
||||
private:
|
||||
class RippleState:public LayerDrawable::LayerState{
|
||||
public:
|
||||
std::vector<int>mTouchThemeAttrs;
|
||||
int mMaxRadius;
|
||||
int mRippleStyle=FORCE_PATTERNED_STYLE?STYLE_PATTERNED:STYLE_SOLID;
|
||||
ColorStateList*mColor;
|
||||
RippleState(LayerState* orig, RippleDrawable* owner);
|
||||
~RippleState();
|
||||
@ -31,19 +35,25 @@ private:
|
||||
Rect mDrawingBounds;
|
||||
Rect mDirtyBounds;
|
||||
std::shared_ptr<RippleState>mState;
|
||||
Drawable* mMask;
|
||||
Drawable* mMask;/*The masking layer, e.g. the layer with id R.id.mask. */
|
||||
RippleBackground* mBackground;
|
||||
|
||||
bool mHasValidMask;
|
||||
bool mRippleActive;
|
||||
RippleForeground* mRipple;
|
||||
bool mHasPending;
|
||||
bool mOverrideBounds;
|
||||
float mPendingX;
|
||||
float mPendingY;
|
||||
bool mHasPending;
|
||||
std::vector<RippleForeground*>mExitingRipples;
|
||||
int mDensity;
|
||||
bool mOverrideBounds;
|
||||
float mBackgroundOpacity;
|
||||
float mTargetBackgroundOpacity;
|
||||
bool mForceSoftware;
|
||||
bool mAddRipple;
|
||||
bool mRunBackgroundAnimation;
|
||||
bool mExitingAnimation;
|
||||
RippleForeground* mRipple;
|
||||
ValueAnimator*mBackgroundAnimation;
|
||||
private:
|
||||
RippleDrawable(std::shared_ptr<RippleState> state);
|
||||
void cancelExitingRipples();
|
||||
@ -59,10 +69,19 @@ private:
|
||||
void drawContent(Canvas& canvas);
|
||||
void drawBackgroundAndRipples(Canvas& canvas);
|
||||
void drawMask(Canvas& canvas);
|
||||
void drawSolid(Canvas& canvas);
|
||||
void exitPatternedBackgroundAnimation();
|
||||
void startPatternedAnimation();
|
||||
void exitPatternedAnimation();
|
||||
void enterPatternedBackgroundAnimation(bool focused, bool hovered);
|
||||
void startBackgroundAnimation();
|
||||
void drawPatterned(Canvas& canvas);
|
||||
void drawPatternedBackground(Canvas& c, float cx, float cy);
|
||||
protected:
|
||||
bool onStateChange(const std::vector<int>&stateSet)override;
|
||||
void onBoundsChange(const Rect& bounds)override;
|
||||
public:
|
||||
RippleDrawable();
|
||||
RippleDrawable(const ColorStateList* color,Drawable* content,Drawable* mask);
|
||||
void jumpToCurrentState()override;
|
||||
int getOpacity()override;
|
||||
@ -76,7 +95,7 @@ public:
|
||||
bool setDrawableByLayerId(int id, Drawable* drawable)override;
|
||||
void setPaddingMode(int mode);
|
||||
bool canApplyTheme()override;
|
||||
void getHotspotBounds(Rect&out)override;
|
||||
void getHotspotBounds(Rect&out)const override;
|
||||
void setHotspot(float x,float y)override;
|
||||
void setHotspotBounds(int left,int top,int w,int h)override;
|
||||
void draw(Canvas& canvas);
|
||||
|
@ -22,8 +22,14 @@ RippleForeground::RippleForeground(RippleDrawable* owner,const Rect& bounds, flo
|
||||
mStartRadius = std::max(bounds.width, bounds.height) * 0.3f;
|
||||
clampStartingPosition();
|
||||
mAnimationListener.onAnimationEnd=[this](Animator&anim,bool isReverse){
|
||||
mHasFinishedExit = true;
|
||||
pruneSwFinished();
|
||||
mHasFinishedExit = true;
|
||||
auto it = std::find(mRunningSwAnimators.begin(),mRunningSwAnimators.end(),&anim);
|
||||
if(it != mRunningSwAnimators.end()){
|
||||
mRunningSwAnimators.erase(it);
|
||||
LOGV("Animator %p ended",&anim);
|
||||
delete &anim;
|
||||
}
|
||||
//pruneSwFinished();
|
||||
};
|
||||
}
|
||||
|
||||
@ -38,9 +44,8 @@ void RippleForeground::onTargetRadiusChanged(float targetRadius){
|
||||
for (auto animator:mRunningSwAnimators) {
|
||||
animator->removeListener(mAnimationListener);
|
||||
animator->end();
|
||||
delete animator;
|
||||
}
|
||||
mRunningSwAnimators.clear();
|
||||
//mRunningSwAnimators.clear();
|
||||
invalidateSelf();//switchToUiThreadAnimation();
|
||||
}
|
||||
|
||||
@ -57,11 +62,11 @@ void RippleForeground::drawSoftware(Canvas& c,float origAlpha) {
|
||||
|
||||
void RippleForeground::pruneSwFinished() {
|
||||
if( mRunningSwAnimators.size()==0)return;
|
||||
for (int i=mRunningSwAnimators.size()-1;i>=0;i--){
|
||||
for (int i=mRunningSwAnimators.size();i>=0;i--){
|
||||
Animator*anim=mRunningSwAnimators[i];
|
||||
if (!anim->isRunning()) {
|
||||
mRunningSwAnimators.erase(mRunningSwAnimators.begin()+i);
|
||||
delete anim;
|
||||
LOGV("erase %p",anim);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -98,6 +103,7 @@ float RippleForeground::getOpacity()const{
|
||||
void RippleForeground::startSoftwareEnter() {
|
||||
for (auto anim:mRunningSwAnimators) {
|
||||
anim->cancel();
|
||||
LOGV("delete anim %p of %d",anim,mRunningSwAnimators.size());
|
||||
delete anim;
|
||||
}
|
||||
mRunningSwAnimators.clear();
|
||||
@ -105,7 +111,6 @@ void RippleForeground::startSoftwareEnter() {
|
||||
tweenRadius->setDuration(RIPPLE_ENTER_DURATION);
|
||||
tweenRadius->setInterpolator(DecelerateInterpolator::gDecelerateInterpolator.get());//DECELERATE_INTERPOLATOR);
|
||||
tweenRadius->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this](ValueAnimator&anim){
|
||||
LOGV("mTweenRadius=%f [%f,%f,%f] opacity=%f",getCurrentRadius(),mStartRadius,mTargetRadius,mOpacity);
|
||||
mTweenRadius = GET_VARIANT(anim.getAnimatedValue(),float);
|
||||
onAnimationPropertyChanged();
|
||||
}));
|
||||
@ -130,6 +135,7 @@ void RippleForeground::startSoftwareEnter() {
|
||||
onAnimationPropertyChanged();
|
||||
}));
|
||||
opacity->start();
|
||||
LOGV("add anims %p %p %p",tweenRadius,tweenOrigin,opacity);
|
||||
mRunningSwAnimators.push_back(opacity);
|
||||
}
|
||||
|
||||
@ -144,6 +150,7 @@ void RippleForeground::startSoftwareExit() {
|
||||
}));
|
||||
|
||||
opacity->start();
|
||||
LOGV("add anim %p",opacity);
|
||||
mRunningSwAnimators.push_back(opacity);
|
||||
}
|
||||
|
||||
@ -171,6 +178,7 @@ float RippleForeground::getCurrentRadius() {
|
||||
void RippleForeground::end(){
|
||||
for (auto anim:mRunningSwAnimators) {
|
||||
anim->end();
|
||||
LOGV("delete %d anim %p",mRunningSwAnimators.size(),anim);
|
||||
delete anim;
|
||||
}
|
||||
mRunningSwAnimators.clear();
|
||||
|
@ -39,7 +39,7 @@ private:
|
||||
bool mForceSoftware;
|
||||
float mStartRadius = 0;
|
||||
std::vector<Animator*> mRunningSwAnimators;
|
||||
AnimatorListenerAdapter mAnimationListener;
|
||||
Animator::AnimatorListener mAnimationListener;
|
||||
private:
|
||||
float getCurrentX();
|
||||
float getCurrentY();
|
||||
@ -50,7 +50,7 @@ private:
|
||||
void onAnimationPropertyChanged();
|
||||
void pruneSwFinished();
|
||||
protected:
|
||||
void onTargetRadiusChanged(float targetRadius);
|
||||
void onTargetRadiusChanged(float targetRadius)override;
|
||||
void clampStartingPosition();
|
||||
public:
|
||||
RippleForeground(RippleDrawable* owner,const Rect& bounds, float startingX, float startingY, bool forceSoftware);
|
||||
|
Loading…
Reference in New Issue
Block a user