fix a crash caused by drawablecontainer

This commit is contained in:
侯歌 2022-02-28 12:41:42 +08:00
parent 64cb5cfce3
commit 29527883f9
17 changed files with 210 additions and 50 deletions

View File

@ -111,15 +111,15 @@ bool AnimatedStateListDrawable::selectTransition(int toIndex){
Transition* transition = nullptr;
Drawable* d = getCurrent();
/*if (dynamic_cast<AnimationDrawable*>(d)) {
if (dynamic_cast<AnimationDrawable*>(d)) {
bool reversed = mState->isTransitionReversed(fromId, toId);
transition = new AnimationDrawableTransition((AnimationDrawable*) d,reversed, hasReversibleFlag);
} else if (dynamic_cast<AnimatedVectorDrawable*>(d)) {
}/* else if (dynamic_cast<AnimatedVectorDrawable*>(d)) {
bool reversed = mState->isTransitionReversed(fromId, toId);
transition = new AnimatedVectorDrawableTransition((AnimatedVectorDrawable*) d, reversed, hasReversibleFlag);
} else if (dynamic_cast<Animatable*>(d)) {
}*/ else if (dynamic_cast<Animatable*>(d)) {
transition = new AnimatableTransition((Animatable*) d);
} else*/ {
} else {
// We don't know how to animate this transition.
return false;
}
@ -170,6 +170,12 @@ void AnimatedStateListDrawable::setConstantState(std::shared_ptr<DrawableContain
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void AnimatedStateListDrawable::Transition::reverse(){
}
bool AnimatedStateListDrawable::Transition::canReverse(){
return false;
}
AnimatedStateListDrawable::AnimatedStateListState::AnimatedStateListState(const AnimatedStateListDrawable::AnimatedStateListState* orig,AnimatedStateListDrawable* owner)
:StateListState(orig,owner){
@ -287,4 +293,78 @@ float AnimatedStateListDrawable::FrameInterpolator::getInterpolation(float input
}
//----------------------------------------------------------------------------------------------------------
AnimatedStateListDrawable::AnimatableTransition::AnimatableTransition(Animatable* a) {
mA = a;
}
void AnimatedStateListDrawable::AnimatableTransition::start() {
mA->start();
}
void AnimatedStateListDrawable::AnimatableTransition::stop() {
mA->stop();
}
/***************************/
AnimatedStateListDrawable::AnimationDrawableTransition::AnimationDrawableTransition(AnimationDrawable* ad, bool reversed, bool hasReversibleFlag){
const int frameCount = ad->getNumberOfFrames();
const int fromFrame = reversed ? frameCount - 1 : 0;
const int toFrame = reversed ? 0 : frameCount - 1;
FrameInterpolator* interp = new FrameInterpolator(ad, reversed);
ObjectAnimator* anim = ObjectAnimator::ofInt(ad, "currentIndex",{fromFrame, toFrame});
anim->setAutoCancel(true);
anim->setDuration(interp->getTotalDuration());
anim->setInterpolator(interp);
mHasReversibleFlag = hasReversibleFlag;
mAnim = anim;
}
bool AnimatedStateListDrawable::AnimationDrawableTransition::canReverse() {
return mHasReversibleFlag;
}
void AnimatedStateListDrawable::AnimationDrawableTransition::start() {
mAnim->start();
}
void AnimatedStateListDrawable::AnimationDrawableTransition::reverse() {
mAnim->reverse();
}
void AnimatedStateListDrawable::AnimationDrawableTransition::stop() {
mAnim->cancel();
}
/***************************/
AnimatedStateListDrawable::AnimatedVectorDrawableTransition::AnimatedVectorDrawableTransition(AnimatedVectorDrawable* avd,bool reversed, bool hasReversibleFlag){
mAvd = avd;
mReversed = reversed;
mHasReversibleFlag = hasReversibleFlag;
}
bool AnimatedStateListDrawable::AnimatedVectorDrawableTransition::canReverse(){
return mHasReversibleFlag;// && mAvd->canReverse();
}
void AnimatedStateListDrawable::AnimatedVectorDrawableTransition::start(){
if (mReversed) {
reverse();
} else {
//mAvd->start();
}
}
void AnimatedStateListDrawable::AnimatedVectorDrawableTransition::reverse(){
if (canReverse()) {
//mAvd->reverse();
} else {
LOGW("Can't reverse, either the reversible is set to false,"
" or the AnimatedVectorDrawable can't reverse");
}
}
void AnimatedStateListDrawable::AnimatedVectorDrawableTransition::stop(){
//mAvd->stop();
}
}//endof namespace

View File

@ -3,6 +3,7 @@
#include <drawables/statelistdrawable.h>
#include <drawables/animationdrawable.h>
#include <animation/interpolators.h>
#include <animation/objectanimator.h>
#include <core/sparsearray.h>
namespace cdroid{
@ -45,11 +46,54 @@ protected:
virtual void start()=0;
virtual void stop()=0;
virtual void reverse()=0;
virtual void reverse();
// Not supported by default.
virtual bool canReverse() {
return false;
}
virtual bool canReverse();
};
class AnimatableTransition:public Transition {
private:
Animatable* mA;
public:
AnimatableTransition(Animatable* a);
void start()override;
void stop()override;
};
class AnimationDrawableTransition:public Transition {
private:
ObjectAnimator* mAnim;
// Even AnimationDrawable is always reversible technically, but
// we should obey the XML's android:reversible flag.
bool mHasReversibleFlag;
public:
AnimationDrawableTransition(AnimationDrawable* ad,
bool reversed, bool hasReversibleFlag);
bool canReverse()override;
void start()override;
void reverse()override;
void stop()override;
};
typedef Drawable AnimatedVectorDrawable;
class AnimatedVectorDrawableTransition:public Transition {
private:
AnimatedVectorDrawable* mAvd;
// mReversed is indicating the current transition's direction.
bool mReversed;
// mHasReversibleFlag is indicating whether the whole transition has
// reversible flag set to true.
// If mHasReversibleFlag is false, then mReversed is always false.
bool mHasReversibleFlag;
public:
AnimatedVectorDrawableTransition(AnimatedVectorDrawable* avd,
bool reversed, bool hasReversibleFlag);
bool canReverse()override;
void start()override;
void reverse()override;
void stop()override;
};
private:
std::shared_ptr<AnimatedStateListState> mState;

View File

@ -44,6 +44,10 @@ BitmapDrawable::BitmapState::BitmapState(const BitmapState&bitmapState){
mAutoMirrored = bitmapState.mAutoMirrored;
}
BitmapDrawable::BitmapState::~BitmapState(){
delete mTint;
}
Drawable* BitmapDrawable::BitmapState::newDrawable(){
return new BitmapDrawable(shared_from_this());
}
@ -211,6 +215,7 @@ void BitmapDrawable::setTintMode(int tintMode) {
invalidateSelf();
}
}
std::shared_ptr<Drawable::ConstantState>BitmapDrawable::getConstantState(){
return mBitmapState;
}

View File

@ -33,6 +33,7 @@ private:
BitmapState();
BitmapState(RefPtr<ImageSurface>bitmap);
BitmapState(const BitmapState&bitmapState);
~BitmapState()override;
Drawable* newDrawable()override;
int getChangingConfigurations()const override;
};

View File

@ -9,6 +9,9 @@
namespace cdroid{
Drawable::ConstantState::~ConstantState(){
}
Drawable::Drawable(){
mLevel=0;
mChangingConfigurations=0;

View File

@ -52,6 +52,7 @@ public:
public:
virtual Drawable* newDrawable()=0;
virtual int getChangingConfigurations()const=0;
virtual ~ConstantState();
};
enum{
DEFAULT_TINT_MODE=SRC_IN

View File

@ -47,6 +47,7 @@ DrawableContainer::DrawableContainerState::DrawableContainerState(const Drawable
mAutoMirrored = false;
mMutated = false;
mDither = false;
mCheckedStateful = false;
mLayoutDirection = LayoutDirection::LTR;
mEnterFadeDuration= 0;
mExitFadeDuration = 0;
@ -113,6 +114,7 @@ DrawableContainer::DrawableContainerState::DrawableContainerState(const Drawable
mDrawables[i]=d;
}
}
DrawableContainer::DrawableContainerState::~DrawableContainerState(){
for_each( mDrawables.begin(), mDrawables.end(),[](Drawable*d){delete d;});
mDrawables.clear();
@ -136,7 +138,6 @@ Drawable*DrawableContainer::DrawableContainerState::getChild(int index){
Drawable* prepared = prepareDrawable(cs->newDrawable());
mDrawables[index] = prepared;
LOGV("getChild(%d)=%p",index,prepared);
mDrawableFutures.erase(it);
return prepared;
}
}
@ -269,10 +270,12 @@ int DrawableContainer::DrawableContainerState::getConstantWidth() {
if (!mCheckedConstantSize) computeConstantSize();
return mConstantWidth;
}
int DrawableContainer::DrawableContainerState::getConstantHeight() {
if (!mCheckedConstantSize) computeConstantSize();
return mConstantHeight;
}
int DrawableContainer::DrawableContainerState::getConstantMinimumWidth() {
if (!mCheckedConstantSize)computeConstantSize();
return mConstantMinimumWidth;
@ -291,13 +294,10 @@ Drawable* DrawableContainer::DrawableContainerState::prepareDrawable(Drawable* c
}
void DrawableContainer::DrawableContainerState::createAllFutures(){
if (mDrawableFutures.size()) {
int futureCount = mDrawableFutures.size();
for (int keyIndex = 0; keyIndex < futureCount; keyIndex++) {
auto cs = mDrawableFutures[keyIndex];
mDrawables[keyIndex] = prepareDrawable(cs->newDrawable());
}
mDrawableFutures.clear();//=nullptr;
const int futureCount = mDrawableFutures.size();
for (int keyIndex = 0; keyIndex < futureCount; keyIndex++) {
auto cs = mDrawableFutures[keyIndex];
mDrawables[keyIndex] = prepareDrawable(cs->newDrawable());
}
}

29
src/gui/drawables/levellistdrawable.cc Normal file → Executable file
View File

@ -6,16 +6,27 @@ namespace cdroid{
LevelListDrawable::LevelListState::LevelListState(const LevelListState*orig,LevelListDrawable*own)
:DrawableContainerState(orig,own){
if(orig!=nullptr){
mLows = orig->mLows;
if(orig!=nullptr){
mLows = orig->mLows;
mHighs= orig->mHighs;
}
}
}
void LevelListDrawable::LevelListState::mutate(){
//mLows = mLows.clone();
// mHighs = mHighs.clone();
}
int LevelListDrawable::LevelListState::indexOfLevel(int level)const{
const int N = getChildCount();
for (int i = 0; i < N; i++) {
if (level >= mLows[i] && level <= mHighs[i]) {
return i;
}
}
return -1;
}
Drawable*LevelListDrawable::LevelListState::newDrawable(){
return new LevelListDrawable(std::dynamic_pointer_cast<LevelListState>(shared_from_this()));
}
@ -34,7 +45,7 @@ LevelListDrawable::LevelListDrawable(std::shared_ptr<LevelListState>state){
}
bool LevelListDrawable::onLevelChange(int level){
int idx =indexOfLevel(level);
int idx = mLevelListState->indexOfLevel(level);
if (selectDrawable(idx)) {
return true;
}
@ -72,16 +83,6 @@ void LevelListDrawable::addLevel(int low,int high,Drawable* drawable) {
onLevelChange(getLevel());
}
int LevelListDrawable::indexOfLevel(int level){
const int N = getChildCount();
for (int i = 0; i < N; i++) {
if (level >= mLevelListState->mLows[i] && level <= mLevelListState->mHighs[i]) {
return i;
}
}
return -1;
}
Drawable*LevelListDrawable::inflate(Context*ctx,const AttributeSet&atts){
return new LevelListDrawable();
}

2
src/gui/drawables/levellistdrawable.h Normal file → Executable file
View File

@ -11,11 +11,11 @@ private:
LevelListState(const LevelListState*orig,LevelListDrawable*own);
LevelListState(const LevelListState&state);
void mutate();
int indexOfLevel(int level)const;
Drawable*newDrawable()override;
};
bool mMutated;
std::shared_ptr<LevelListState>mLevelListState;
int indexOfLevel(int level);
LevelListDrawable(std::shared_ptr<LevelListState>state);
protected:
bool onLevelChange(int level)override;

View File

@ -8,6 +8,7 @@ namespace cdroid{
NinePatchDrawable::NinePatchDrawable(std::shared_ptr<NinePatchState>state){
mNinePatchState=state;
mAlpha=255;
mMutated =false;
mTintFilter=nullptr;
computeBitmapSize();
}
@ -15,6 +16,7 @@ NinePatchDrawable::NinePatchDrawable(std::shared_ptr<NinePatchState>state){
NinePatchDrawable::NinePatchDrawable(Context*ctx,const std::string&resid){
mNinePatchState=std::make_shared<NinePatchState>(ctx->getImage(resid));
mAlpha=255;
mMutated =false;
mTintFilter=nullptr;
computeBitmapSize();
}
@ -23,6 +25,7 @@ NinePatchDrawable::NinePatchDrawable(RefPtr<ImageSurface>bmp){
mNinePatchState=std::make_shared<NinePatchState>(bmp);
mAlpha=255;
mTintFilter=nullptr;
mMutated =false;
computeBitmapSize();
}

8
src/gui/res/color/textview.xml Normal file → Executable file
View File

@ -1,5 +1,5 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item state_focused="false" alpha="#ff" color="#ffff0000"/>
<item state_focused="true" alpha="#ff" color="#ff00ff00"/>
<item alpha="#ff" color="#ff0000ff"/>
<selector xmlns:cdroid="http://schemas.android.com/apk/res/android">
<item cdroid:state_focused="false" cdroid:alpha="#ff" cdroid:color="#ffff0000"/>
<item cdroid:state_focused="true" cdroid:alpha="#ff" cdroid:color="#ff00ff00"/>
<item cdroid:alpha="#ff" cdroid:color="#ff0000ff"/>
</selector>

View File

@ -27,6 +27,7 @@ void AbsListView::FLY_start(int initialVelocity) {
mFlingStrictSpan = StrictMode.enterCriticalSpan("AbsListView-fling");
}*/
}
void AbsListView::FLY_startSpringback() {
mSuppressIdleStateChangeCall = false;
if (mScroller->springBack(0, mScrollY, 0, 0, 0, 0)) {
@ -38,6 +39,7 @@ void AbsListView::FLY_startSpringback() {
reportScrollStateChange(OnScrollListener::SCROLL_STATE_IDLE);
}
}
void AbsListView::FLY_startOverfling(int initialVelocity) {
mScroller->setInterpolator(nullptr);
mScroller->fling(0, mScrollY, 0, initialVelocity, 0, 0,INT_MIN,INT_MAX, 0, getHeight());
@ -46,6 +48,7 @@ void AbsListView::FLY_startOverfling(int initialVelocity) {
invalidate();
postOnAnimation(mFlingRunnable);
}
void AbsListView::FLY_edgeReached(int delta) {
mScroller->notifyVerticalEdgeReached(mScrollY, 0, mOverflingDistance);
int overscrollMode = getOverScrollMode();
@ -71,6 +74,7 @@ void AbsListView::FLY_startScroll(int distance, int duration, bool linear, bool
mSuppressIdleStateChangeCall = suppressEndFlingStateChangeCall;
postOnAnimation(mFlingRunnable);
}
void AbsListView::FLY_endFling() {
mTouchMode = TOUCH_MODE_REST;
@ -245,7 +249,7 @@ void AbsListView::initAbsListView() {
mIsChildViewEnabled =false;
mIsDetaching =false;
mSuppressIdleStateChangeCall =false;
mVelocityScale =1.0f;
mVelocityScale = 1.0f;
mLastScrollState = OnScrollListener::SCROLL_STATE_IDLE;
mOnScrollListener.onScroll = nullptr;
mOnScrollListener.onScrollStateChanged = nullptr;
@ -257,12 +261,14 @@ void AbsListView::initAbsListView() {
mFlingRunnable = std::bind(&AbsListView::FLY_Proc,this);
mCheckFlywheel = std::bind(&AbsListView::FLY_CheckFlyWheelProc,this);
mWidthMeasureSpec=0;
mSelector =nullptr;
mSelector = nullptr;
mDataSetObserver =nullptr;
mLayoutMode=LAYOUT_FORCE_TOP;
mTouchMode =TOUCH_MODE_REST ;
mDrawSelectorOnTop=true;
mSmoothScrollbarEnabled =true;
mCacheColorHint = 0;
mResurrectToPosition = INVALID_POSITION;
mLayoutMode = LAYOUT_FORCE_TOP;
mTouchMode = TOUCH_MODE_REST ;
mDrawSelectorOnTop = true;
mSmoothScrollbarEnabled = true;
ViewConfiguration& configuration = ViewConfiguration::get(mContext);
mTouchSlop = configuration.getScaledTouchSlop();
mVerticalScrollFactor = configuration.getScaledVerticalScrollFactor();

View File

@ -21,6 +21,7 @@ void GridView::initGridView(){
mRequestedColumnWidth=0;
mHorizontalSpacing=0;
mVerticalSpacing=0;
mRequestedHorizontalSpacing = 0;
mStretchMode = STRETCH_COLUMN_WIDTH;
mReferenceView=nullptr;
mReferenceViewInSelectedRow=nullptr;

View File

@ -836,6 +836,7 @@ RelativeLayout::LayoutParams::LayoutParams(Context*ctx,const AttributeSet&atts):
mRules[ALIGN_PARENT_START] = atts.getBoolean("layout_alignParentStart", false) ? LTRUE : 0;
mRules[ALIGN_PARENT_END] = atts.getBoolean("layout_alignParentEnd" , false) ? LTRUE : 0;
mRulesChanged = true;
mNeedsLayoutResolution = false;
memcpy(mInitialRules,mRules,sizeof(mRules));
}

View File

@ -66,6 +66,7 @@ void TabLayout::initTabLayout(){
mScrollAnimator = nullptr;
mViewPager = nullptr;
mPagerAdapter = nullptr;
mTabIndicatorGravity = Gravity::BOTTOM;
mAdapterChangeListener= nullptr;
mTabSelectedIndicator = nullptr;
mRequestedTabMinWidth = INVALID_WIDTH;

View File

@ -238,9 +238,10 @@ bool ViewGroup::dispatchTransformedTouchEvent(MotionEvent& event, bool cancel,
float offsetX = mScrollX - child->mLeft;
float offsetY = mScrollY - child->mTop;
transformedEvent->offsetLocation(offsetX, offsetY);
/*if (! child->hasIdentityMatrix()) {
transformedEvent.transform(child.getInverseMatrix());
}*/
if (! child->hasIdentityMatrix()) {
Matrix mtx=child->getInverseMatrix();
transformedEvent->transform((const float*)&mtx);
}
handled = child->dispatchTouchEvent(*transformedEvent);
}
@ -382,11 +383,11 @@ bool ViewGroup::dispatchGenericFocusedEvent(MotionEvent&event){
bool ViewGroup::dispatchTransformedGenericPointerEvent(MotionEvent& event, View* child) {
bool handled;
/*if (!child->hasIdentityMatrix()) {
MotionEvent transformedEvent = getTransformedMotionEvent(event, child);
handled = child.dispatchGenericMotionEvent(transformedEvent);
transformedEvent.recycle();
} else */{
if (!child->hasIdentityMatrix()) {
MotionEvent* transformedEvent = getTransformedMotionEvent(event, child);
handled = child->dispatchGenericMotionEvent(*transformedEvent);
transformedEvent->recycle();
} else {
float offsetX = mScrollX - child->mLeft;
float offsetY = mScrollY - child->mTop;
event.offsetLocation(offsetX, offsetY);
@ -2260,6 +2261,18 @@ bool ViewGroup::dispatchKeyEvent(KeyEvent&event){
return View::dispatchKeyEvent(event);
}
MotionEvent* ViewGroup::getTransformedMotionEvent(MotionEvent& event, View* child) {
const float offsetX = mScrollX - child->mLeft;
const float offsetY = mScrollY - child->mTop;
MotionEvent* transformedEvent = MotionEvent::obtain(event);
transformedEvent->offsetLocation(offsetX, offsetY);
if (!child->hasIdentityMatrix()) {
Matrix mtx=child->getInverseMatrix();
transformedEvent->transform((const float*)&mtx);
}
return transformedEvent;
}
bool ViewGroup::dispatchTouchEvent(MotionEvent&ev){
const int action = ev.getAction();
const int actionMasked=ev.getActionMasked();

View File

@ -131,7 +131,7 @@ private:
void removePointersFromTouchTargets(int pointerIdBits);
void cancelTouchTarget(View* view);
void cancelHoverTarget(View*view);
MotionEvent* getTransformedMotionEvent(MotionEvent& event, View* child);
bool dispatchTransformedTouchEvent(MotionEvent& event, bool cancel,
View* child, int desiredPointerIdBits);
bool dispatchTransformedGenericPointerEvent(MotionEvent& event, View* child);