mirror of
https://gitee.com/houstudio/Cdroid.git
synced 2024-11-29 18:59:14 +08:00
add drawable hotspot support
This commit is contained in:
parent
916cf9decc
commit
ef0b2447f8
@ -62,6 +62,14 @@ int Drawable::getOpacity(){
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
void Drawable::setHotspot(float x,float y){
|
||||
}
|
||||
void Drawable::setHotspotBounds(int left,int top,int width,int height){
|
||||
}
|
||||
void Drawable::getHotspotBounds(Rect&outRect){
|
||||
outRect=mBounds;
|
||||
}
|
||||
|
||||
std::shared_ptr<Drawable::ConstantState>Drawable::getConstantState(){
|
||||
return nullptr;
|
||||
}
|
||||
@ -327,7 +335,7 @@ static int parseColor(const std::string&value){
|
||||
}
|
||||
|
||||
static void parseShapeGradient(Shape*shape,const AttributeSet&atts){
|
||||
std::vector<int>cls;
|
||||
std::vector<uint32_t>cls;
|
||||
|
||||
cls.push_back(atts.getColor("startColor"));
|
||||
if(atts.hasAttribute("centerColor"))
|
||||
|
@ -88,7 +88,9 @@ public:
|
||||
bool setLevel(int level);
|
||||
int getLevel()const{return mLevel;}
|
||||
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 bool getPadding(Rect&padding);
|
||||
virtual Insets getOpticalInsets();
|
||||
virtual bool isStateful()const;
|
||||
|
@ -88,12 +88,12 @@ void RippleBackground::onStateChanged(){
|
||||
mAnimator = ValueAnimator::ofFloat({mOpacity,newOpacity});//this, OPACITY, newOpacity);
|
||||
mAnimator->setDuration(OPACITY_DURATION);
|
||||
mAnimator->setInterpolator(new LinearInterpolator());//LINEAR_INTERPOLATOR);
|
||||
mAnimator->addUpdateListener([this](ValueAnimator&anim){
|
||||
mAnimator->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this](ValueAnimator&anim){
|
||||
FloatPropertyValuesHolder*fp=(FloatPropertyValuesHolder*)anim.getValues(0);
|
||||
LOGD("mOpacity=%f",fp->getAnimatedValue());
|
||||
mOpacity=fp->getAnimatedValue();
|
||||
invalidateSelf();
|
||||
});
|
||||
}));
|
||||
|
||||
mAnimator->start();
|
||||
}
|
||||
|
@ -15,11 +15,11 @@ protected:
|
||||
float mDensityScale;
|
||||
|
||||
void invalidateSelf();
|
||||
void onHotspotBoundsChanged();
|
||||
virtual void onTargetRadiusChanged(float targetRadius);
|
||||
public:
|
||||
RippleComponent(RippleDrawable* owner,const Rect& bounds);
|
||||
void onBoundsChange();
|
||||
virtual void onHotspotBoundsChanged();
|
||||
virtual void onBoundsChange();
|
||||
void setup(float maxRadius, int densityDpi);
|
||||
void getBounds(Rect& bounds);
|
||||
};
|
||||
|
@ -51,7 +51,7 @@ RippleDrawable::RippleDrawable(std::shared_ptr<RippleState> state) {
|
||||
|
||||
RippleDrawable::RippleDrawable(ColorStateList* color,Drawable* content,Drawable* mask)
|
||||
:RippleDrawable(std::make_shared<RippleState>(nullptr,nullptr)){
|
||||
if(content)addLayer(content,{0},0,0,0,0,0);
|
||||
if(content)addLayer(content,{0},-1,0,0,0,0);
|
||||
if(mask)addLayer(mask,{0},MASK_LAYER_ID,0,0,0,0);
|
||||
setColor(color);
|
||||
ensurePadding();
|
||||
@ -134,7 +134,7 @@ void RippleDrawable::onBoundsChange(const Rect& bounds){
|
||||
|
||||
if (!mOverrideBounds) {
|
||||
mHotspotBounds=bounds;
|
||||
//onHotspotBoundsChanged();
|
||||
onHotspotBoundsChanged();
|
||||
}
|
||||
|
||||
for (auto ripple:mExitingRipples) {
|
||||
@ -261,6 +261,40 @@ void RippleDrawable::tryRippleExit(){
|
||||
}
|
||||
|
||||
void RippleDrawable::clearHotspots(){
|
||||
if(mRipple){
|
||||
mRipple->end();
|
||||
mRipple =nullptr;
|
||||
mRippleActive =false;
|
||||
}
|
||||
if(mBackground)
|
||||
mBackground->setState(false,false,false);
|
||||
cancelExitingRipples();
|
||||
}
|
||||
|
||||
void RippleDrawable::setHotspot(float x,float y){
|
||||
mHasPending=(mRipple==nullptr)||(mBackground ==nullptr);
|
||||
if (mHasPending){
|
||||
mPendingX =x;
|
||||
mPendingY = y;
|
||||
}
|
||||
if(mRipple)mRipple->move(x,y);
|
||||
}
|
||||
|
||||
void RippleDrawable::setHotspotBounds(int left,int top,int w,int h){
|
||||
mOverrideBounds = true;
|
||||
mHotspotBounds.set(left,top,w,h);
|
||||
onHotspotBoundsChanged();
|
||||
}
|
||||
|
||||
void RippleDrawable::getHotspotBounds(Rect&out){
|
||||
out=mHotspotBounds;
|
||||
}
|
||||
|
||||
void RippleDrawable::onHotspotBoundsChanged(){
|
||||
for(auto ripple:mExitingRipples)
|
||||
ripple->onHotspotBoundsChanged();
|
||||
if(mRipple)mRipple->onHotspotBoundsChanged();
|
||||
if(mBackground)mBackground->onHotspotBoundsChanged();
|
||||
}
|
||||
|
||||
void RippleDrawable::draw(Canvas& canvas){
|
||||
@ -307,7 +341,36 @@ void RippleDrawable::pruneRipples() {
|
||||
for (int i = remaining; i < count; i++) {
|
||||
delete mExitingRipples[i];
|
||||
}
|
||||
mExitingRipples.clear();
|
||||
mExitingRipples.resize(remaining);
|
||||
}
|
||||
|
||||
int RippleDrawable::getMaskType(){
|
||||
if (mRipple == nullptr && mExitingRipples.size()<= 0
|
||||
&& (mBackground == nullptr || !mBackground->isVisible())) {
|
||||
// We might need a mask later.
|
||||
return MASK_UNKNOWN;
|
||||
}
|
||||
|
||||
if (mMask) {
|
||||
if (mMask->getOpacity() == OPAQUE) {
|
||||
// Clipping handles opaque explicit masks.
|
||||
return MASK_NONE;
|
||||
} else {
|
||||
return MASK_EXPLICIT;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for non-opaque, non-mask content.
|
||||
std::vector<ChildDrawable*>& array = mLayerState->mChildren;
|
||||
int count = array.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (array[i]->mDrawable->getOpacity() != OPAQUE) {
|
||||
return MASK_CONTENT;
|
||||
}
|
||||
}
|
||||
|
||||
// Clipping handles opaque content.
|
||||
return MASK_NONE;
|
||||
}
|
||||
|
||||
void RippleDrawable::drawContent(Canvas& canvas) {
|
||||
@ -331,9 +394,7 @@ void RippleDrawable::drawBackgroundAndRipples(Canvas& canvas) {
|
||||
const float x = mHotspotBounds.centerX();
|
||||
const float y = mHotspotBounds.centerY();
|
||||
canvas.translate(x, y);
|
||||
|
||||
int color=mState->mColor->getColorForState(getState(),0xFF000000);
|
||||
if((color>>24)>0x80)color=(color&0x00FFFFFF)|0x80000000;
|
||||
int color=mState->mColor->getColorForState(getState(),0xFF888888);
|
||||
canvas.set_color(color);
|
||||
|
||||
if (mBackground && mBackground->isVisible()) {
|
||||
@ -341,6 +402,9 @@ void RippleDrawable::drawBackgroundAndRipples(Canvas& canvas) {
|
||||
}
|
||||
|
||||
for (auto ripple:mExitingRipples) {
|
||||
int alpha=0x80*ripple->getOpacity();
|
||||
color=(color&0x00FFFFFF)|(alpha<<24);
|
||||
canvas.set_color(color);
|
||||
ripple->draw(canvas,1.f);
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ private:
|
||||
float mPendingY;
|
||||
bool mHasPending;
|
||||
std::vector<RippleForeground*>mExitingRipples;
|
||||
int mDensity;
|
||||
int mDensity;
|
||||
bool mOverrideBounds;
|
||||
bool mForceSoftware;
|
||||
private:
|
||||
@ -53,7 +53,9 @@ private:
|
||||
void tryRippleEnter();
|
||||
void tryRippleExit();
|
||||
void clearHotspots();
|
||||
void onHotspotBoundsChanged();
|
||||
void updateLocalState();
|
||||
int getMaskType();
|
||||
void drawContent(Canvas& canvas);
|
||||
void drawBackgroundAndRipples(Canvas& canvas);
|
||||
void drawMask(Canvas& canvas);
|
||||
@ -63,17 +65,20 @@ protected:
|
||||
public:
|
||||
RippleDrawable(ColorStateList* color,Drawable* content,Drawable* mask);
|
||||
void jumpToCurrentState()override;
|
||||
int getOpacity()override;
|
||||
int getOpacity()override;
|
||||
bool setVisible(bool visible, bool restart)override;
|
||||
bool isProjected();
|
||||
bool isStateful()const override;
|
||||
bool hasFocusStateSpecified()const override;
|
||||
void setColor(ColorStateList* color);
|
||||
void setRadius(int radius);
|
||||
int getRadius()const;
|
||||
int getRadius()const;
|
||||
bool setDrawableByLayerId(int id, Drawable* drawable)override;
|
||||
void setPaddingMode(int mode);
|
||||
bool canApplyTheme()override;
|
||||
void getHotspotBounds(Rect&out)override;
|
||||
void setHotspot(float x,float y)override;
|
||||
void setHotspotBounds(int left,int top,int w,int h)override;
|
||||
void draw(Canvas& canvas);
|
||||
void invalidateSelf()override;
|
||||
void invalidateSelf(bool invalidateMask);
|
||||
|
@ -20,7 +20,7 @@ RippleForeground::RippleForeground(RippleDrawable* owner,const Rect& bounds, flo
|
||||
|
||||
void RippleForeground::onTargetRadiusChanged(float targetRadius){
|
||||
clampStartingPosition();
|
||||
//switchToUiThreadAnimation();
|
||||
invalidateSelf();//switchToUiThreadAnimation();
|
||||
}
|
||||
|
||||
void RippleForeground::drawSoftware(Canvas& c,float origAlpha) {
|
||||
@ -29,23 +29,24 @@ void RippleForeground::drawSoftware(Canvas& c,float origAlpha) {
|
||||
if (alpha > 0 && radius > 0) {
|
||||
const float x = getCurrentX();
|
||||
const float y = getCurrentY();
|
||||
c.arc(x, y, radius,0,M_PI*2.);
|
||||
c.arc(x,y, radius,0,M_PI*2.);
|
||||
c.fill();
|
||||
}
|
||||
}
|
||||
|
||||
void RippleForeground::pruneSwFinished() {
|
||||
for (auto it=mRunningSwAnimators.begin();it!=mRunningSwAnimators.end();){
|
||||
if ((*it)->isRunning()) {
|
||||
if (!(*it)->isRunning()) {
|
||||
Animator*anim=(*it);
|
||||
it=mRunningSwAnimators.erase(it);
|
||||
}else it++;
|
||||
}
|
||||
}
|
||||
|
||||
void RippleForeground::getBounds(Rect& bounds) {
|
||||
int outerX = (int) mTargetX;
|
||||
int outerY = (int) mTargetY;
|
||||
int r = (int) mTargetRadius + 1;
|
||||
const int outerX = (int) mTargetX;
|
||||
const int outerY = (int) mTargetY;
|
||||
const int r = (int) mTargetRadius + 1;
|
||||
bounds.set(outerX - r, outerY - r, r+r,r + r);
|
||||
}
|
||||
|
||||
@ -60,72 +61,76 @@ bool RippleForeground::hasFinishedExit()const{
|
||||
}
|
||||
|
||||
long RippleForeground::computeFadeOutDelay() {
|
||||
long timeSinceEnter = SystemClock::uptimeMillis() - mEnterStartedAtMillis;
|
||||
long timeSinceEnter = AnimationUtils::currentAnimationTimeMillis() - mEnterStartedAtMillis;
|
||||
if (timeSinceEnter > 0 && timeSinceEnter < OPACITY_HOLD_DURATION) {
|
||||
return OPACITY_HOLD_DURATION - timeSinceEnter;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
float RippleForeground::getOpacity()const{
|
||||
return mOpacity;
|
||||
}
|
||||
|
||||
void RippleForeground::startSoftwareEnter() {
|
||||
for (auto anim:mRunningSwAnimators) {
|
||||
anim->cancel();
|
||||
anim->cancel();
|
||||
delete anim;
|
||||
}
|
||||
mRunningSwAnimators.clear();
|
||||
|
||||
ValueAnimator* tweenRadius = ValueAnimator::ofFloat({.0f,1.f});//this, TWEEN_RADIUS, 1);
|
||||
tweenRadius->setDuration(RIPPLE_ENTER_DURATION);
|
||||
tweenRadius->setInterpolator(new DecelerateInterpolator());//DECELERATE_INTERPOLATOR);
|
||||
tweenRadius->addUpdateListener([this](ValueAnimator&anim){
|
||||
tweenRadius->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this](ValueAnimator&anim){
|
||||
FloatPropertyValuesHolder*fp=(FloatPropertyValuesHolder*)anim.getValues(0);
|
||||
LOGV("mTweenRadius=%f",fp->getAnimatedValue());
|
||||
LOGV("mTweenRadius=%f [%f,%f,%f] opacity=%f",fp->getAnimatedValue(),getCurrentRadius(),mStartRadius,mTargetRadius,mOpacity);
|
||||
mTweenRadius=fp->getAnimatedValue();
|
||||
onAnimationPropertyChanged();
|
||||
});
|
||||
}));
|
||||
tweenRadius->start();
|
||||
mRunningSwAnimators.push_back(tweenRadius);
|
||||
|
||||
ValueAnimator* tweenOrigin = ValueAnimator::ofFloat({.0f,1.f});//this, TWEEN_ORIGIN, 1);
|
||||
tweenOrigin->setDuration(RIPPLE_ORIGIN_DURATION);
|
||||
tweenOrigin->setInterpolator(new DecelerateInterpolator());//DECELERATE_INTERPOLATOR);
|
||||
tweenOrigin->addUpdateListener([this](ValueAnimator&anim){
|
||||
tweenOrigin->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this](ValueAnimator&anim){
|
||||
FloatPropertyValuesHolder*fp=(FloatPropertyValuesHolder*)anim.getValues(0);
|
||||
mTweenX=mTweenY=fp->getAnimatedValue();
|
||||
onAnimationPropertyChanged();
|
||||
});
|
||||
}));
|
||||
tweenOrigin->start();
|
||||
mRunningSwAnimators.push_back(tweenOrigin);
|
||||
|
||||
ValueAnimator* opacity = ValueAnimator::ofFloat({.0f,1.f});//this, OPACITY, 1);
|
||||
opacity->setDuration(OPACITY_ENTER_DURATION);
|
||||
opacity->setInterpolator(new LinearInterpolator());//LINEAR_INTERPOLATOR);
|
||||
opacity->addUpdateListener([this](ValueAnimator&anim){
|
||||
opacity->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this](ValueAnimator&anim){
|
||||
FloatPropertyValuesHolder*fp=(FloatPropertyValuesHolder*)anim.getValues(0);
|
||||
mOpacity=fp->getAnimatedValue();
|
||||
onAnimationPropertyChanged();
|
||||
});
|
||||
}));
|
||||
opacity->start();
|
||||
mRunningSwAnimators.push_back(opacity);
|
||||
}
|
||||
|
||||
void RippleForeground::startSoftwareExit() {
|
||||
|
||||
ValueAnimator* opacity = ValueAnimator::ofFloat({1.f,.0f});
|
||||
ValueAnimator* opacity = ValueAnimator::ofFloat({.0f,1.f});
|
||||
opacity->setDuration(OPACITY_EXIT_DURATION);
|
||||
opacity->setInterpolator(new LinearInterpolator());//LINEAR_INTERPOLATOR);
|
||||
opacity->addListener(mAnimationListener);
|
||||
opacity->setStartDelay(computeFadeOutDelay());
|
||||
opacity->addUpdateListener([this](ValueAnimator&anim){
|
||||
opacity->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this](ValueAnimator&anim){
|
||||
FloatPropertyValuesHolder*fp=(FloatPropertyValuesHolder*)anim.getValues(0);
|
||||
mOpacity=fp->getAnimatedValue();
|
||||
});
|
||||
}));
|
||||
|
||||
opacity->start();
|
||||
mRunningSwAnimators.push_back(opacity);
|
||||
}
|
||||
|
||||
void RippleForeground::enter(){
|
||||
mEnterStartedAtMillis = SystemClock::uptimeMillis();
|
||||
mEnterStartedAtMillis = AnimationUtils::currentAnimationTimeMillis();
|
||||
startSoftwareEnter();
|
||||
}
|
||||
|
||||
@ -150,10 +155,6 @@ void RippleForeground::end(){
|
||||
anim->end();
|
||||
}
|
||||
mRunningSwAnimators.clear();
|
||||
/*for (auto animhw:mRunningHwAnimators;) {
|
||||
animhw->end();
|
||||
}
|
||||
mRunningHwAnimators.clear();*/
|
||||
}
|
||||
|
||||
void RippleForeground::onAnimationPropertyChanged() {
|
||||
@ -165,13 +166,6 @@ void RippleForeground::onAnimationPropertyChanged() {
|
||||
void RippleForeground::draw(Canvas&canvas,float alpha){
|
||||
pruneSwFinished();
|
||||
drawSoftware(canvas,alpha);
|
||||
/*const bool hasDisplayListCanvas = !mForceSoftware && c instanceof DisplayListCanvas;
|
||||
if (hasDisplayListCanvas) {
|
||||
DisplayListCanvas hw = (DisplayListCanvas) c;
|
||||
drawHardware(hw, p);
|
||||
} else {
|
||||
drawSoftware(c, p);
|
||||
}*/
|
||||
}
|
||||
|
||||
void RippleForeground::clampStartingPosition(){
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <drawables/ripplebackground.h>
|
||||
#include <animation/animationutils.h>
|
||||
namespace cdroid{
|
||||
|
||||
class RippleForeground:public RippleComponent{
|
||||
@ -57,6 +58,7 @@ public:
|
||||
void move(float x, float y);
|
||||
bool hasFinishedExit()const;
|
||||
long computeFadeOutDelay();
|
||||
float getOpacity()const;
|
||||
void enter();
|
||||
void exit();
|
||||
void end();
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <color.h>
|
||||
#include <cdlog.h>
|
||||
|
||||
|
||||
namespace cdroid{
|
||||
|
||||
Shape::Shape(){
|
||||
@ -62,7 +61,7 @@ int Shape::getStroke(int& color)const{
|
||||
return mStrokeWidth;
|
||||
}
|
||||
|
||||
void Shape::setGradientColors(const std::vector<int>&cls){
|
||||
void Shape::setGradientColors(const std::vector<uint32_t>&cls){
|
||||
mGradientColors=cls;
|
||||
mRebuildGradient=true;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ protected:
|
||||
float mCenterX,mCenterY;
|
||||
bool mRebuildGradient;
|
||||
bool bUseLevel;
|
||||
std::vector<int>mGradientColors;//size 0:nofill, 1:solid fill 2,3:gradient fill
|
||||
std::vector<uint32_t>mGradientColors;//size 0:nofill, 1:solid fill 2,3:gradient fill
|
||||
RefPtr<Pattern>mPaint;//used to fill
|
||||
void rebuildPattern(const Rect&r);
|
||||
virtual void onResize(int width,int height){}
|
||||
@ -34,7 +34,7 @@ public:
|
||||
void setStrokeDash(int width,int gap);
|
||||
int getStroke(int &color)const;//return line width,color
|
||||
void setSolidColor(int color);
|
||||
void setGradientColors(const std::vector<int>&cls);//gradient fill colors
|
||||
void setGradientColors(const std::vector<uint32_t>&cls);//gradient fill colors
|
||||
void setGradientAngle(float angle);
|
||||
void setGradientRadius(float radius);
|
||||
void setGradientType(int gt);
|
||||
|
@ -529,7 +529,7 @@ void AbsListView::positionSelector(int position, View* sel, bool manageHotspot,
|
||||
}
|
||||
updateSelectorState();
|
||||
}
|
||||
//if (manageHotspot) selector->setHotspot(x, y);
|
||||
if (manageHotspot) selector->setHotspot(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1186,7 +1186,7 @@ void AbsListView::checkTap(int x,int y) {
|
||||
((TransitionDrawable*) d)->resetTransition();
|
||||
}
|
||||
}
|
||||
//mSelector->setHotspot(x, y);
|
||||
mSelector->setHotspot(x, y);
|
||||
}
|
||||
|
||||
if (longClickable) {
|
||||
@ -2027,6 +2027,13 @@ bool AbsListView::onKeyUp(int keyCode, KeyEvent& event) {
|
||||
}
|
||||
|
||||
void AbsListView::dispatchSetPressed(bool pressed) {
|
||||
// Don't dispatch setPressed to our children. We call setPressed on ourselves to
|
||||
// get the selector in the right state, but we don't want to press each child.
|
||||
}
|
||||
|
||||
void AbsListView::dispatchDrawableHotspotChanged(float x, float y){
|
||||
// Don't dispatch hotspot changes to children. We'll manually handle
|
||||
// calling drawableHotspotChanged on the correct child.
|
||||
}
|
||||
|
||||
int AbsListView::pointToPosition(int x, int y) {
|
||||
@ -2705,7 +2712,7 @@ void AbsListView::onTouchUp(MotionEvent&ev) {
|
||||
if (d && dynamic_cast<TransitionDrawable*>(d)) {
|
||||
((TransitionDrawable*) d)->resetTransition();
|
||||
}
|
||||
//mSelector->setHotspot(x, ev.getY());
|
||||
mSelector->setHotspot(x, ev.getY());
|
||||
}
|
||||
if (mTouchModeReset != nullptr) {
|
||||
removeCallbacks(mTouchModeReset);
|
||||
|
@ -321,6 +321,7 @@ public:
|
||||
|
||||
bool verifyDrawable(Drawable* dr)const override;
|
||||
void jumpDrawablesToCurrentState()override;
|
||||
void dispatchDrawableHotspotChanged(float x, float y)override;
|
||||
int pointToPosition(int x, int y);
|
||||
long pointToRowId(int x, int y);
|
||||
bool performItemClick(View* view, int position, long id)override;
|
||||
|
@ -101,6 +101,11 @@ void AbsSeekBar::drawableStateChanged(){
|
||||
}
|
||||
}
|
||||
|
||||
void AbsSeekBar::drawableHotspotChanged(float x,float y){
|
||||
ProgressBar::drawableHotspotChanged(x,y);
|
||||
if(mThumb)mThumb->setHotspot(x,y);
|
||||
}
|
||||
|
||||
bool AbsSeekBar::verifyDrawable(Drawable* who)const{
|
||||
return who == mThumb || who == mTickMark || ProgressBar::verifyDrawable(who);
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ public:
|
||||
virtual void setMax(int max);
|
||||
virtual bool canUserSetProgress()const;
|
||||
void onRtlPropertiesChanged(int layoutDirection)override;
|
||||
void drawableHotspotChanged(float x,float y)override;
|
||||
};
|
||||
|
||||
}//namespace
|
||||
|
@ -37,6 +37,11 @@ void CompoundButton::drawableStateChanged() {
|
||||
}
|
||||
}
|
||||
|
||||
void CompoundButton::drawableHotspotChanged(float x,float y){
|
||||
Button::drawableHotspotChanged(x,y);
|
||||
if(mButtonDrawable)mButtonDrawable->setHotspot(x,y);
|
||||
}
|
||||
|
||||
int CompoundButton::getHorizontalOffsetForDrawables()const{
|
||||
return (mButtonDrawable == nullptr) ?0: mButtonDrawable->getIntrinsicWidth();
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ public:
|
||||
void setOnCheckedChangeListener(OnCheckedChangeListener listener);
|
||||
/*OnCheckedChangeWidgetListener internal use(for radiogroup...)*/
|
||||
void setOnCheckedChangeWidgetListener(OnCheckedChangeListener listener);
|
||||
void drawableHotspotChanged(float x,float y)override;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
@ -307,6 +307,7 @@ bool ImageView::setFrame(int l, int t, int w, int h){
|
||||
configureBounds();
|
||||
return changed;
|
||||
}
|
||||
|
||||
void ImageView::configureBounds(){
|
||||
if (mDrawable == nullptr /*|| !mHaveFrame*/) return;
|
||||
const int mPaddingLeft=0,mPaddingRight=0,mPaddingTop=0,mPaddingBottom=0;
|
||||
@ -390,6 +391,19 @@ void ImageView::configureBounds(){
|
||||
mDrawMatrix.xx,mDrawMatrix.yx,mDrawMatrix.xy,mDrawMatrix.yy,mDrawMatrix.x0,mDrawMatrix.y0);
|
||||
}
|
||||
|
||||
void ImageView::drawableStateChanged(){
|
||||
View::drawableStateChanged();
|
||||
if(mDrawable && mDrawable->isStateful()
|
||||
&& mDrawable->setState(getDrawableState())){
|
||||
invalidateDrawable(*mDrawable);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageView::drawableHotspotChanged(float x, float y){
|
||||
View::drawableHotspotChanged(x,y);
|
||||
if(mDrawable)mDrawable->setHotspot(x,y);
|
||||
}
|
||||
|
||||
void ImageView::invalidateDrawable(Drawable& dr){
|
||||
if (mDrawable==&dr) {
|
||||
// update cached drawable dimensions if they've changed
|
||||
|
@ -55,8 +55,8 @@ protected:
|
||||
void configureBounds();
|
||||
bool setFrame(int l, int t, int w, int h)override;
|
||||
void onMeasure(int widthMeasureSpec, int heightMeasureSpec)override;
|
||||
void drawableStateChanged()override;
|
||||
virtual void onDraw(Canvas& canvas) override;
|
||||
public:
|
||||
public:
|
||||
explicit ImageView(int w, int h);
|
||||
ImageView(Context*ctx,const AttributeSet&attrs);
|
||||
@ -97,6 +97,7 @@ public:
|
||||
void setImageLevel(int level);
|
||||
void setSelected(bool selected)override;
|
||||
void setImageState(const std::vector<int>&state, bool merge);
|
||||
void drawableHotspotChanged(float x, float y)override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -129,6 +129,12 @@ void ProgressBar::drawableStateChanged(){
|
||||
updateDrawableState();
|
||||
}
|
||||
|
||||
void ProgressBar::drawableHotspotChanged(float x, float y){
|
||||
View::drawableHotspotChanged(x,y);
|
||||
if(mProgressDrawable)mProgressDrawable->setHotspot(x,y);
|
||||
if(mIndeterminateDrawable)mIndeterminateDrawable->setHotspot(x,y);
|
||||
}
|
||||
|
||||
bool ProgressBar::verifyDrawable(Drawable* who)const{
|
||||
return who == mProgressDrawable || who == mIndeterminateDrawable|| View::verifyDrawable(who);
|
||||
}
|
||||
@ -179,10 +185,10 @@ void ProgressBar::doRefreshProgress(int id, int progress, bool fromUser,bool cal
|
||||
mAnimator->setAutoCancel(true);
|
||||
mAnimator->setDuration(PROGRESS_ANIM_DURATION);
|
||||
mAnimator->setInterpolator(new DecelerateInterpolator());
|
||||
mAnimator->addUpdateListener([this](ValueAnimator&anim){
|
||||
mAnimator->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this](ValueAnimator&anim){
|
||||
FloatPropertyValuesHolder*fp=(FloatPropertyValuesHolder*)anim.getValues(0);
|
||||
setVisualProgress(ID_PRIMARY,fp->getAnimatedValue());
|
||||
});
|
||||
}));
|
||||
}
|
||||
prop=(FloatPropertyValuesHolder*)mAnimator->getValues(0);
|
||||
prop->setValues({scale});
|
||||
|
@ -124,6 +124,7 @@ public:
|
||||
int getSecondaryProgressTintMode()const;
|
||||
Drawable* getTintTarget(int layerId, bool shouldFallback);
|
||||
void setProgressDrawableTiled(Drawable* d);
|
||||
void drawableHotspotChanged(float x, float y)override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -511,10 +511,10 @@ void TabLayout::ensureScrollAnimator(){
|
||||
mScrollAnimator = new ValueAnimator();
|
||||
mScrollAnimator->setInterpolator(new FastOutSlowInInterpolator());
|
||||
mScrollAnimator->setDuration(ANIMATION_DURATION);
|
||||
mScrollAnimator->addUpdateListener([this](ValueAnimator&anim) {
|
||||
mScrollAnimator->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this](ValueAnimator&anim) {
|
||||
IntPropertyValuesHolder*ip=(IntPropertyValuesHolder*)anim.getValues()[0];
|
||||
scrollTo(ip->getAnimatedValue(), 0);
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1240,10 +1240,10 @@ void TabLayout::SlidingTabStrip::animateIndicatorToPosition(int position, int du
|
||||
ValueAnimator* animator = mIndicatorAnimator;
|
||||
animator->setDuration(duration);
|
||||
animator->removeAllListeners();
|
||||
animator->addUpdateListener([this,startLeft,targetLeft,startRight,targetRight](ValueAnimator&anim) {
|
||||
animator->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this,startLeft,targetLeft,startRight,targetRight](ValueAnimator&anim) {
|
||||
const float fraction = anim.getAnimatedFraction();
|
||||
setIndicatorPosition(lerp(startLeft, targetLeft, fraction),lerp(startRight, targetRight, fraction));
|
||||
});
|
||||
}));
|
||||
Animator::AnimatorListener al;
|
||||
al.onAnimationEnd=[this,position](Animator&anim,bool reverse){
|
||||
mSelectedPosition = position;
|
||||
|
@ -939,6 +939,7 @@ void TextView::setCompoundDrawablesWithIntrinsicBounds(const std::string& left,
|
||||
setCompoundDrawablesWithIntrinsicBounds(context->getDrawable(left),context->getDrawable(top),
|
||||
context->getDrawable(right),context->getDrawable(bottom));
|
||||
}
|
||||
|
||||
void TextView::drawableStateChanged(){
|
||||
View::drawableStateChanged();
|
||||
|
||||
@ -958,6 +959,14 @@ void TextView::drawableStateChanged(){
|
||||
}
|
||||
}
|
||||
|
||||
void TextView::drawableHotspotChanged(float x,float y){
|
||||
View::drawableHotspotChanged(x,y);
|
||||
for(int i=0;mDrawables&&(i<4);i++){
|
||||
Drawable* dr=mDrawables->mShowing[i];
|
||||
if(dr)dr->setHotspot(x,y);
|
||||
}
|
||||
}
|
||||
|
||||
void TextView::updateTextColors(){
|
||||
bool inval = false;
|
||||
const std::vector<int>&drawableState = getDrawableState();
|
||||
|
@ -199,6 +199,7 @@ public:
|
||||
std::vector<Drawable*>getCompoundDrawables();
|
||||
void setCompoundDrawableTintList(ColorStateList* tint);
|
||||
ColorStateList* getCompoundDrawableTintList();
|
||||
void drawableHotspotChanged(float x,float y)override;
|
||||
void setCompoundDrawableTintMode(int tintMode);
|
||||
int getCompoundDrawableTintMode();
|
||||
|
||||
|
@ -2828,6 +2828,18 @@ void View::drawableStateChanged(){
|
||||
if(changed) invalidate(true);
|
||||
}
|
||||
|
||||
void View::drawableHotspotChanged(float x, float y){
|
||||
if(mBackground)mBackground->setHotspot(x,y);
|
||||
if(mDefaultFocusHighlight)mDefaultFocusHighlight->setHotspot(x,y);
|
||||
if(mForegroundInfo && mForegroundInfo->mDrawable)
|
||||
mForegroundInfo->mDrawable->setHotspot(x,y);
|
||||
dispatchDrawableHotspotChanged(x,y);
|
||||
}
|
||||
|
||||
void View::dispatchDrawableHotspotChanged(float x,float y){
|
||||
//NOTHING
|
||||
}
|
||||
|
||||
void View::refreshDrawableState(){
|
||||
mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
|
||||
drawableStateChanged();
|
||||
@ -3543,7 +3555,7 @@ void View::setPressed(bool pressed){
|
||||
}
|
||||
|
||||
void View::setPressed(bool pressed,int x,int y){
|
||||
//if(pressed)drawableHotspotChanged(x,y);
|
||||
if(pressed)drawableHotspotChanged(x,y);
|
||||
setPressed(pressed);
|
||||
}
|
||||
|
||||
@ -4753,7 +4765,7 @@ bool View::onTouchEvent(MotionEvent& event){
|
||||
}
|
||||
break;
|
||||
case MotionEvent::ACTION_MOVE:
|
||||
//if (clickable)drawableHotspotChanged(x, y);
|
||||
if (clickable)drawableHotspotChanged(x, y);
|
||||
|
||||
// Be lenient about moving outside of buttons
|
||||
if (!pointInView(x, y,ViewConfiguration::get(mContext).getScaledTouchSlop())) {
|
||||
|
@ -587,6 +587,8 @@ public:
|
||||
bool isFocusableInTouchMode()const;
|
||||
virtual void setFocusable(int focusable);
|
||||
virtual void setFocusableInTouchMode(bool focusableInTouchMode);
|
||||
virtual void drawableHotspotChanged(float x, float y);
|
||||
virtual void dispatchDrawableHotspotChanged(float x,float y);
|
||||
void refreshDrawableState();
|
||||
bool isDefaultFocusHighlightNeeded(const Drawable* background,const Drawable* foreground)const;
|
||||
virtual const std::vector<int>getDrawableState();
|
||||
|
@ -731,6 +731,18 @@ void ViewGroup::dispatchSetPressed(bool pressed) {
|
||||
}
|
||||
}
|
||||
|
||||
void ViewGroup::dispatchDrawableHotspotChanged(float x,float y){
|
||||
for(auto child:mChildren){
|
||||
const bool nonActivationable = !child->isClickable()&&!child->isLongClickable();
|
||||
const bool duplicateState = (child->mViewFlags & DUPLICATE_PARENT_STATE)!=0;
|
||||
if( nonActivationable||duplicateState){
|
||||
float point[2]={x,y};
|
||||
transformPointToViewLocal(point,*child);
|
||||
child->drawableHotspotChanged(point[0],point[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ViewGroup::getChildCount()const{
|
||||
return mChildren.size();
|
||||
}
|
||||
|
@ -193,6 +193,7 @@ protected:
|
||||
void drawableStateChanged()override;
|
||||
std::vector<int> onCreateDrawableState()const override;
|
||||
void dispatchSetPressed(bool pressed)override;
|
||||
void dispatchDrawableHotspotChanged(float x,float y)override;
|
||||
virtual int getChildDrawingOrder(int childCount, int i);
|
||||
std::vector<View*> buildOrderedChildList();
|
||||
|
||||
|
@ -22,14 +22,25 @@ TEST_F(ANIMATOR,callback){
|
||||
app.exec();
|
||||
}
|
||||
|
||||
TEST_F(ANIMATOR,ofInt){
|
||||
TEST_F(ANIMATOR,ofInt1){
|
||||
ValueAnimator*anim=ValueAnimator::ofInt({0,100});
|
||||
anim->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this](ValueAnimator&anim){
|
||||
IntPropertyValuesHolder*ip=(IntPropertyValuesHolder*)anim.getValues(0);
|
||||
LOGD("value=%d",ip->getAnimatedValue());
|
||||
}));
|
||||
for(int i=0;i<=10;i++){
|
||||
anim->setCurrentFraction((float)i/10.f);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ANIMATOR,ofInt2){
|
||||
IntPropertyValuesHolder iprop;
|
||||
iprop.setValues({0,100});
|
||||
ValueAnimator*anim=ValueAnimator::ofPropertyValuesHolder({&iprop});
|
||||
anim->addUpdateListener([this](ValueAnimator&anim){
|
||||
anim->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this](ValueAnimator&anim){
|
||||
IntPropertyValuesHolder*ip=(IntPropertyValuesHolder*)anim.getValues(0);
|
||||
LOGD("value=%d",ip->getAnimatedValue());
|
||||
});
|
||||
}));
|
||||
for(int i=0;i<=10;i++){
|
||||
anim->setCurrentFraction((float)i/10.f);
|
||||
}
|
||||
@ -39,10 +50,26 @@ TEST_F(ANIMATOR,ofFloat){
|
||||
FloatPropertyValuesHolder fprop;
|
||||
fprop.setValues({0,100});
|
||||
ValueAnimator*anim=ValueAnimator::ofPropertyValuesHolder({&fprop});
|
||||
anim->addUpdateListener([this](ValueAnimator&anim){
|
||||
anim->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this](ValueAnimator&anim){
|
||||
FloatPropertyValuesHolder*fp=(FloatPropertyValuesHolder*)anim.getValues(0);
|
||||
LOGD("value=%f",fp->getAnimatedValue());
|
||||
});
|
||||
}));
|
||||
for(int i=0;i<=10;i++){
|
||||
anim->setCurrentFraction((float)i/10.f);
|
||||
}
|
||||
}
|
||||
|
||||
class MyProperty: public Property{
|
||||
public:
|
||||
MyProperty(const std::string&name):Property(name){
|
||||
}
|
||||
void set(void* object, float value)override{
|
||||
LOGD("value=%f",value);
|
||||
}
|
||||
};
|
||||
TEST_F(ANIMATOR,ofProperty){
|
||||
MyProperty*myprop=new MyProperty("test");
|
||||
ObjectAnimator*anim=ObjectAnimator::ofInt(nullptr,myprop,{0,100});
|
||||
for(int i=0;i<=10;i++){
|
||||
anim->setCurrentFraction((float)i/10.f);
|
||||
}
|
||||
@ -54,10 +81,10 @@ TEST_F(ANIMATOR,loopdrivered){
|
||||
iprop.setValues({0,100});
|
||||
|
||||
ValueAnimator*anim=ValueAnimator::ofPropertyValuesHolder({&iprop});
|
||||
anim->addUpdateListener([this](ValueAnimator&anim){
|
||||
anim->addUpdateListener(ValueAnimator::AnimatorUpdateListener([this](ValueAnimator&anim){
|
||||
IntPropertyValuesHolder*fp=(IntPropertyValuesHolder*)anim.getValues(0);
|
||||
LOGD("value=%d",fp->getAnimatedValue());
|
||||
});
|
||||
}));
|
||||
anim->setDuration(2000);
|
||||
anim->start();
|
||||
app.exec();
|
||||
@ -82,14 +109,14 @@ TEST_F(ANIMATOR,translate){
|
||||
cprop.setValues({0xFF000000,0xFFFF8844});
|
||||
|
||||
ValueAnimator*anim=ValueAnimator::ofPropertyValuesHolder({&xprop,&yprop,&cprop});
|
||||
anim->addUpdateListener([tv](ValueAnimator&anim){
|
||||
anim->addUpdateListener(ValueAnimator::AnimatorUpdateListener([tv](ValueAnimator&anim){
|
||||
IntPropertyValuesHolder*xp=(IntPropertyValuesHolder*)anim.getValues(0);
|
||||
IntPropertyValuesHolder*yp=(IntPropertyValuesHolder*)anim.getValues(1);
|
||||
ColorPropertyValuesHolder*cp=(ColorPropertyValuesHolder*)anim.getValues(2);
|
||||
tv->setPos(xp->getAnimatedValue(),tv->getTop());
|
||||
tv->setPos(tv->getLeft(),yp->getAnimatedValue());
|
||||
tv->setBackgroundColor(cp->getAnimatedValue());
|
||||
});
|
||||
}));
|
||||
|
||||
anim->setDuration(5000);
|
||||
anim->start();
|
||||
@ -107,12 +134,12 @@ TEST_F(ANIMATOR,scale){
|
||||
fprop.setValues({0,2.0});
|
||||
|
||||
ValueAnimator*anim=ValueAnimator::ofPropertyValuesHolder({&fprop});
|
||||
anim->addUpdateListener([tv](ValueAnimator&anim){
|
||||
anim->addUpdateListener(ValueAnimator::AnimatorUpdateListener([tv](ValueAnimator&anim){
|
||||
FloatPropertyValuesHolder*fp=(FloatPropertyValuesHolder*)anim.getValues(0);
|
||||
float scale=fp->getAnimatedValue();
|
||||
tv->setScaleX(scale);
|
||||
tv->setScaleY(scale);
|
||||
});
|
||||
}));
|
||||
anim->setDuration(5000);
|
||||
anim->start();
|
||||
app.exec();
|
||||
|
Loading…
Reference in New Issue
Block a user