animationdrawable working well with progressbar

This commit is contained in:
侯歌 2021-12-03 14:15:21 +08:00
parent 0180530844
commit 402b723467
8 changed files with 218 additions and 10 deletions

View File

@ -38,8 +38,16 @@ int main(int argc,const char*argv[]){
pb3->setProgressDrawable(new ColorDrawable(0xFF112233));
pb3->setIndeterminate(true);
ProgressBar*pb4=new ProgressBar(72,72);
AnimationDrawable*ad=new AnimationDrawable();
ad->addFrame(new ColorDrawable(0xFFFF0000),500);
ad->addFrame(new ColorDrawable(0xFF00FF00),500);
ad->addFrame(new ColorDrawable(0xFF0000FF),500);
w->addView(pb4).setId(105).setPos(880,60);
pb4->setIndeterminateDrawable(ad);
pb4->setIndeterminate(true);
pb4->setProgressDrawable(new ColorDrawable(0xFF111111));
//////////////////////////////////////////////////////////
SeekBar*sb = new SeekBar(800,50);
SeekBar*sb2= new SeekBar(800,50);

View File

@ -46,7 +46,7 @@ public:
bool operator!=(std::nullptr_t)const{
return fun!=nullptr;
}
R operator()(Args...args)const{
virtual R operator()(Args...args){
return fun(std::forward<Args>(args)...);
}
};

View File

@ -18,6 +18,7 @@
#include <drawables/levellistdrawable.h>
#include <drawables/layerdrawable.h>
#include <drawables/statelistdrawable.h>
#include <drawables/animationdrawable.h>
#include <drawables/gradientdrawable.h>
#include <drawables/scrollbardrawable.h>
#include <drawables/rippledrawable.h>

View File

@ -0,0 +1,150 @@
#include <drawables/animationdrawable.h>
#include <core/systemclock.h>
#include <cdlog.h>
namespace cdroid{
AnimationDrawable::AnimationDrawable():AnimationDrawable(nullptr){
}
AnimationDrawable::AnimationDrawable(std::shared_ptr<AnimationDrawable::AnimationState>state){
std::shared_ptr<AnimationState>as =std::make_shared<AnimationState>(state.get(),this);
setConstantState(as);
if(state)setFrame(0,true,false);
mRunnable=std::bind(&AnimationDrawable::run,this);
}
void AnimationDrawable::setConstantState(std::shared_ptr<DrawableContainerState>state){
DrawableContainer::setConstantState(state);
mAnimationState=std::dynamic_pointer_cast<AnimationState>(state);
}
bool AnimationDrawable::setVisible(bool visible,bool restart){
const bool changed=DrawableContainer::setVisible(visible,restart);
if(visible){
if(restart||changed){
const bool startFromZero =restart||(!mRunning&&!mAnimationState->mOneShot)||
mCurFrame>=mAnimationState->getChildCount();
setFrame((startFromZero?0:mCurFrame),true,mAnimating);
}
}else{
unscheduleSelf(mRunnable);
}
}
void AnimationDrawable::start(){
mAnimating = true;
LOGD("mRunning=%d",mRunning);
if(!isRunning())
setFrame(0,false,mAnimationState->getChildCount()>1||!mAnimationState->mOneShot);
}
void AnimationDrawable::stop(){
mAnimating = false;
if(isRunning()){
mCurFrame =0 ;
unscheduleSelf(mRunnable);
}
}
bool AnimationDrawable::isRunning(){
return mRunning;
}
void AnimationDrawable::run(){
nextFrame(false);
}
void AnimationDrawable::unscheduleSelf(Runnable&what){
mRunning = false;
DrawableContainer::unscheduleSelf(what);
}
int AnimationDrawable::getNumberOfFrames(){
return mAnimationState->getChildCount();
}
Drawable* AnimationDrawable::getFrame(int index){
return mAnimationState->getChild(index);
}
int AnimationDrawable::getDuration(int i){
return mAnimationState->mDurations[i];
}
bool AnimationDrawable::isOneShot(){
return mAnimationState->mOneShot;
}
void AnimationDrawable::setOneShot(bool oneShot){
mAnimationState->mOneShot = oneShot;
}
void AnimationDrawable::addFrame(Drawable*frame,int duration){
mAnimationState->addFrame(frame,duration);
if(!mRunning) setFrame(0,true,false);
}
void AnimationDrawable::nextFrame(bool unschedule){
int nextFrame =mCurFrame + 1;
int numFrames =mAnimationState->getChildCount();
bool isLastFrame =mAnimationState->mOneShot && nextFrame>=(numFrames-1);
if(!mAnimationState->mOneShot && nextFrame >= numFrames)
nextFrame=0;
setFrame(nextFrame,unschedule,!isLastFrame);
}
void AnimationDrawable::setFrame(int frame,bool unschedule,bool animate){
if(frame >= mAnimationState->getChildCount())
return;
mAnimating= animate;
mCurFrame = frame;
selectDrawable(frame);
if(unschedule||animate)
unscheduleSelf(mRunnable);
if(animate){
mCurFrame = frame;
mRunning = true;
scheduleSelf(mRunnable,SystemClock::uptimeMillis()+mAnimationState->mDurations[frame]);
}
}
Drawable* AnimationDrawable::mutate(){
if(!mMutated && DrawableContainer::mutate()==this){
mAnimationState->mutate();
mMutated = true;
}
return this;
}
void AnimationDrawable::clearMutated(){
DrawableContainer::clearMutated();
mMutated = false;
}
////////////////////////////////////////////////////////////////////////////////////////////
AnimationDrawable::AnimationState::AnimationState(const AnimationState*orig,AnimationDrawable*owner)
:DrawableContainer::DrawableContainerState(orig,owner){
if(orig){
mDurations=orig->mDurations;
mOneShot =orig->mOneShot;
}else{
mOneShot = false;
}
}
void AnimationDrawable::AnimationState::mutate(){
}
Drawable*AnimationDrawable::AnimationState::newDrawable(){
return new AnimationDrawable(std::dynamic_pointer_cast<AnimationState>(shared_from_this()));
}
void AnimationDrawable::AnimationState::addFrame(Drawable*dr,int dur){
int pos=DrawableContainer::DrawableContainerState::addChild(dr);
if( mDurations.size()<getChildCount())
mDurations.resize(getChildCount());
mDurations[pos]=dur;
}
}

View File

@ -0,0 +1,47 @@
#ifndef __ANIMATION_DRAWABLE_H__
#define __ANIMATION_DRAWABLE_H__
#include <drawables/drawablecontainer.h>
namespace cdroid{
class AnimationDrawable:public DrawableContainer,public Animatable{
private:
class AnimationState:public DrawableContainer::DrawableContainerState{
public:
bool mOneShot;
std::vector<int>mDurations;
AnimationState(const AnimationState*,AnimationDrawable*owner);
void mutate();
Drawable*newDrawable()override;
void addFrame(Drawable*,int dur);
};
std::shared_ptr<AnimationState>mAnimationState;
int mCurFrame;
bool mRunning;
bool mAnimating;
bool mMutated;
Runnable mRunnable;
private:
void setFrame(int frame,bool unschedule,bool animate);
AnimationDrawable(std::shared_ptr<AnimationState>);
protected:
void setConstantState(std::shared_ptr<DrawableContainerState>state)override;
void run();
public:
AnimationDrawable();
bool setVisible(bool visible,bool restart)override;
void start()override;
void stop()override;
bool isRunning()override;
void unscheduleSelf(Runnable& what);
int getNumberOfFrames();
Drawable*getFrame(int index);
int getDuration(int);
bool isOneShot();
void setOneShot(bool oneShot);
void addFrame(Drawable*frame,int duration);
void nextFrame(bool unschedule);
Drawable*mutate()override;
void clearMutated()override;
};
}
#endif

View File

@ -201,11 +201,11 @@ Drawable::Callback* Drawable::getCallback()const{
return mCallback;
}
void Drawable::scheduleSelf(Runnable what, long when){
void Drawable::scheduleSelf(Runnable& what, long when){
if(mCallback)mCallback->scheduleDrawable(*this, what, when);
}
void Drawable::unscheduleSelf(Runnable what){
void Drawable::unscheduleSelf(Runnable& what){
if(mCallback)mCallback->unscheduleDrawable(*this, what);
}

View File

@ -118,8 +118,8 @@ public:
virtual void setChangingConfigurations(int);
void setCallback(Callback*cbk);
Callback* getCallback()const;
void scheduleSelf(Runnable what, long when);
void unscheduleSelf(Runnable what);
void scheduleSelf(Runnable& what, long when);
void unscheduleSelf(Runnable& what);
virtual void invalidateSelf();

View File

@ -70,7 +70,7 @@ ProgressBar::~ProgressBar(){
delete mIndeterminateDrawable;
delete mAnimator;
delete mAnimation;
delete mTransformation;
delete mTransformation;
}
void ProgressBar::initProgressBar(){
@ -93,6 +93,7 @@ void ProgressBar::initProgressBar(){
mIndeterminateDrawable=nullptr;
mAnimator = nullptr;
mAnimation= nullptr;
mInterpolator =nullptr;
mTransformation=nullptr;
mHasAnimation= false;
mInDrawing = false;
@ -479,8 +480,9 @@ void ProgressBar::drawTrack(Canvas&canvas){
d->draw(canvas);
canvas.restore();
if (mShouldStartAnimationDrawable && dynamic_cast<Animatable*>(d)) {
((AnimatedRotateDrawable*) d)->start();
if (mShouldStartAnimationDrawable && dynamic_cast<Animatable*>(d)){
if(dynamic_cast<AnimatedRotateDrawable*>(d)) ((AnimatedRotateDrawable*) d)->start();
if(dynamic_cast<AnimationDrawable*>(d)) ((AnimationDrawable*) d)->start();
mShouldStartAnimationDrawable = false;
}
}
@ -496,7 +498,7 @@ void ProgressBar::updateDrawableBounds(int w,int h){
int top = 0;
int left = 0;
// Aspect ratio logic does not apply to AnimationDrawables
if (mOnlyIndeterminate /*&& !(mIndeterminateDrawable instanceof AnimationDrawable)*/) {
if (mOnlyIndeterminate && !(dynamic_cast<AnimationDrawable*>(mIndeterminateDrawable))) {
// Maintain aspect ratio. Certain kinds of animated drawables
// get very confused otherwise.
const int intrinsicWidth = mIndeterminateDrawable->getIntrinsicWidth();