Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android實現顏色不斷編號的Actionbar

Android實現顏色不斷編號的Actionbar

編輯:關於Android編程

 

\

編輯(11/27/12):添加一個視頻演示結果在Nexus 7運行Android 4.1系統   

 過去一年,ActionBar范式已經成為一個重要的組成部分的過程中,設計和開發一個Android應用程序。事實上,有許多優點,ActionBar幫助開發人員在其應用程序能否經得住時間的考驗。它包含相關操作,可以很容易地定制,是高度可伸縮的,等等。正因為如此,一個人應該總是考慮使用ActionBar UI模式在設計過程在創建一個新的Android應用程序。 

   ActionBar功能很多有趣的樣式的api。這些api允許您品牌你應用程序,這樣,適合你的設計,同時還被辨認在其他的應用程序。簡單來說,就是幾乎沒有限制你能做什麼和一個ActionBar。直到你嘗試做一些更高級的。。。


           為了確保這是可能我創建了一個小小的應用程序與一個ActionBar。我迅速建立了一個AnimationDrawable,開始用一個簡單的調用start()方法,並使用它作為ActionBar的背景。結果很令人失望,因為它不是在所有動畫。探索ActionBarContainer(一個非公有制視圖支持ActionBar)源代碼我注意到它沒有登記callback1我可拉的:

 

[java] 
public void setPrimaryBackground(Drawable bg) { 
    mBackground = bg; 
    invalidate(); 

public void setPrimaryBackground(Drawable bg) {
    mBackground = bg;
    invalidate();
}

     結果,可拉的沒有辦法通知封閉視圖以固定時間間隔重繪本身。從我的角度來看,這是一個想要的行為,以避免這些web -的- - - - 90的紅色到黃色閃爍ActionBars。我終於決定推遲到未來版本的動畫。   

 最近我回到了這個特性/增強,開始開發一個新的Animatable可提取測試目的。這個非常基本的繪圖改變顏色和變化的變化在一個光滑的時尚:

 

[java] 
public class ColorAnimationDrawable extends Drawable implements Animatable { 
 
    private static final long FRAME_DURATION = 1000 / 60; 
    private static final long ANIMATION_DURATION = 1500; 
 
    private static final int ACCCENT_COLOR = 0x33FFFFFF; 
    private static final int DIM_COLOR = 0x33000000; 
 
    private static final Random mRandom = new Random(); 
 
    private final Paint mPaint = new Paint(); 
 
    private boolean mIsRunning; 
 
    private int mStartColor; 
    private int mEndColor; 
    private int mCurrentColor; 
 
    private long mStartTime; 
 
    @Override 
    public void draw(Canvas canvas) { 
        final Rect bounds = getBounds(); 
 
        mPaint.setColor(mCurrentColor); 
        canvas.drawRect(bounds, mPaint); 
 
        mPaint.setColor(ACCCENT_COLOR); 
        canvas.drawRect(bounds.left, bounds.top, bounds.right, bounds.top + 1, mPaint); 
 
        mPaint.setColor(DIM_COLOR); 
        canvas.drawRect(bounds.left, bounds.bottom - 2, bounds.right, bounds.bottom, mPaint); 
    } 
 
    @Override 
    public void setAlpha(int alpha) { 
        oops("setAlpha(int)"); 
    } 
 
    @Override 
    public void setColorFilter(ColorFilter cf) { 
        oops("setColorFilter(ColorFilter)"); 
    } 
 
    @Override 
    public int getOpacity() { 
        return PixelFormat.TRANSPARENT; 
    } 
 
    @Override 
    public void start() { 
        if (!isRunning()) { 
            mIsRunning = true; 
 
            mStartTime = AnimationUtils.currentAnimationTimeMillis(); 
            mStartColor = randomColor(); 
            mEndColor = randomColor(); 
 
            scheduleSelf(mUpdater, SystemClock.uptimeMillis() + FRAME_DURATION); 
            invalidateSelf(); 
        } 
    } 
 
    @Override 
    public void stop() { 
        if (isRunning()) { 
            unscheduleSelf(mUpdater); 
            mIsRunning = false; 
        } 
    } 
 
    @Override 
    public boolean isRunning() { 
        return mIsRunning; 
    } 
 
    private void oops(String message) { 
        throw new UnsupportedOperationException("ColorAnimationDrawable doesn't support " + message); 
    } 
 
    private static int randomColor() { 
        return mRandom.nextInt() & 0x00FFFFFF; 
    } 
 
    private static int evaluate(float fraction, int startValue, int endValue) { 
        return (int) (startValue + fraction * (endValue - startValue)); 
    } 
 
    private final Runnable mUpdater = new Runnable() { 
        @Override 
        public void run() { 
            long now = AnimationUtils.currentAnimationTimeMillis(); 
            long duration = now - mStartTime; 
            if (duration >= ANIMATION_DURATION) { 
                mStartColor = mEndColor; 
                mEndColor = randomColor(); 
                mStartTime = now; 
                mCurrentColor = mStartColor; 
            } else { 
                float fraction = duration / (float) ANIMATION_DURATION; 
                //@formatter:off  
                mCurrentColor = Color.rgb( 
                        evaluate(fraction, Color.red(mStartColor), Color.red(mEndColor)),     // red  
                        evaluate(fraction, Color.green(mStartColor), Color.green(mEndColor)), // green  
                        evaluate(fraction, Color.blue(mStartColor), Color.blue(mEndColor)));  // blue  
                //@formatter:on  
            } 
            scheduleSelf(mUpdater, SystemClock.uptimeMillis() + FRAME_DURATION); 
            invalidateSelf(); 
        } 
    }; 

public class ColorAnimationDrawable extends Drawable implements Animatable {

    private static final long FRAME_DURATION = 1000 / 60;
    private static final long ANIMATION_DURATION = 1500;

    private static final int ACCCENT_COLOR = 0x33FFFFFF;
    private static final int DIM_COLOR = 0x33000000;

    private static final Random mRandom = new Random();

    private final Paint mPaint = new Paint();

    private boolean mIsRunning;

    private int mStartColor;
    private int mEndColor;
    private int mCurrentColor;

    private long mStartTime;

    @Override
    public void draw(Canvas canvas) {
        final Rect bounds = getBounds();

        mPaint.setColor(mCurrentColor);
        canvas.drawRect(bounds, mPaint);

        mPaint.setColor(ACCCENT_COLOR);
        canvas.drawRect(bounds.left, bounds.top, bounds.right, bounds.top + 1, mPaint);

        mPaint.setColor(DIM_COLOR);
        canvas.drawRect(bounds.left, bounds.bottom - 2, bounds.right, bounds.bottom, mPaint);
    }

    @Override
    public void setAlpha(int alpha) {
        oops("setAlpha(int)");
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        oops("setColorFilter(ColorFilter)");
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSPARENT;
    }

    @Override
    public void start() {
        if (!isRunning()) {
            mIsRunning = true;

            mStartTime = AnimationUtils.currentAnimationTimeMillis();
            mStartColor = randomColor();
            mEndColor = randomColor();

            scheduleSelf(mUpdater, SystemClock.uptimeMillis() + FRAME_DURATION);
            invalidateSelf();
        }
    }

    @Override
    public void stop() {
        if (isRunning()) {
            unscheduleSelf(mUpdater);
            mIsRunning = false;
        }
    }

    @Override
    public boolean isRunning() {
        return mIsRunning;
    }

    private void oops(String message) {
        throw new UnsupportedOperationException("ColorAnimationDrawable doesn't support " + message);
    }

    private static int randomColor() {
        return mRandom.nextInt() & 0x00FFFFFF;
    }

    private static int evaluate(float fraction, int startValue, int endValue) {
        return (int) (startValue + fraction * (endValue - startValue));
    }

    private final Runnable mUpdater = new Runnable() {
        @Override
        public void run() {
            long now = AnimationUtils.currentAnimationTimeMillis();
            long duration = now - mStartTime;
            if (duration >= ANIMATION_DURATION) {
                mStartColor = mEndColor;
                mEndColor = randomColor();
                mStartTime = now;
                mCurrentColor = mStartColor;
            } else {
                float fraction = duration / (float) ANIMATION_DURATION;
                //@formatter:off
                mCurrentColor = Color.rgb(
                        evaluate(fraction, Color.red(mStartColor), Color.red(mEndColor)),     // red
                        evaluate(fraction, Color.green(mStartColor), Color.green(mEndColor)), // green
                        evaluate(fraction, Color.blue(mStartColor), Color.blue(mEndColor)));  // blue
                //@formatter:on
            }
            scheduleSelf(mUpdater, SystemClock.uptimeMillis() + FRAME_DURATION);
            invalidateSelf();
        }
    };
}

我認為唯一有趣的事情在這段代碼是使用的方法來激活一個顏色變化。它由提取每個顏色分量和動畫這些值,而不是整個顏色。    

我申請這個可拉的我和boooom ActionBar是工作!我很驚訝,開始調查。在看AOSP源代碼果凍豆MR1釋放,我注意到,這一問題被固定由亞當·鮑威爾(一個工程師在谷歌工作的UI工具包)與a7cc06d。現在的代碼如下所述:

 

[java]
public void setPrimaryBackground(Drawable bg) {    if (mBackground != null) {        mBackground.setCallback(null);        unscheduleDrawable(mBackground);    }    mBackground = bg;    if (bg != null) {        bg.setCallback(this);    }    setWillNotDraw(mIsSplit ? mSplitBackground == null :            mBackground == null && mStackedBackground == null);    invalidate();} 

public void setPrimaryBackground(Drawable bg) {    if (mBackground != null) {        mBackground.setCallback(null);        unscheduleDrawable(mBackground);    }    mBackground = bg;    if (bg != null) {        bg.setCallback(this);    }    setWillNotDraw(mIsSplit ? mSplitBackground == null :            mBackground == null && mStackedBackground == null);    invalidate();}
這個問題,這種修復是它不是用於預api 17構建。所以我想出了一個很簡單的解決辦法,為pre api 17:注冊一個自定義的繪圖。回調,使ActionBarContainer反復設置相同的繪圖與ActionBar的setBackgroundDrawable(繪圖)方法:

 

[java] 
public class MainActivity extends Activity { 
 
    private final Handler mHandler = new Handler(); 
    private ColorAnimationDrawable mActionBarBackground; 
 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main_activity); 
 
        mActionBarBackground = new ColorAnimationDrawable(); 
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { 
            mActionBarBackground.setCallback(mDrawableCallback); 
        } else { 
            getActionBar().setBackgroundDrawable(mActionBarBackground); 
        } 
        mActionBarBackground.start(); 
    } 
 
    @Override 
    protected void onResume() { 
        super.onResume(); 
        mActionBarBackground.start(); 
    } 
 
    @Override 
    protected void onPause() { 
        super.onPause(); 
        mActionBarBackground.stop(); 
    } 
 
    private Drawable.Callback mDrawableCallback = new Drawable.Callback() { 
        @Override 
        public void invalidateDrawable(Drawable who) { 
            getActionBar().setBackgroundDrawable(who); 
        } 
 
        @Override 
        public void scheduleDrawable(Drawable who, Runnable what, long when) { 
            mHandler.postAtTime(what, when); 
        } 
 
        @Override 
        public void unscheduleDrawable(Drawable who, Runnable what) { 
            mHandler.removeCallbacks(what); 
        } 
    }; 

public class MainActivity extends Activity {

    private final Handler mHandler = new Handler();
    private ColorAnimationDrawable mActionBarBackground;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        mActionBarBackground = new ColorAnimationDrawable();
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
            mActionBarBackground.setCallback(mDrawableCallback);
        } else {
            getActionBar().setBackgroundDrawable(mActionBarBackground);
        }
        mActionBarBackground.start();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mActionBarBackground.start();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mActionBarBackground.stop();
    }

    private Drawable.Callback mDrawableCallback = new Drawable.Callback() {
        @Override
        public void invalidateDrawable(Drawable who) {
            getActionBar().setBackgroundDrawable(who);
        }

        @Override
        public void scheduleDrawable(Drawable who, Runnable what, long when) {
            mHandler.postAtTime(what, when);
        }

        @Override
        public void unscheduleDrawable(Drawable who, Runnable what) {
            mHandler.removeCallbacks(what);
        }
    };

 

[java] 

}

 


多虧了這個技巧,你現在可以激活你的背景ActionBar回到API 11但請記住這可能有幾個,有時嚴重的後果在你的應用程序:     

它可以讓你的應用程序看起來不同和更加優美的特色是微小的,微妙的和漂亮的細節     

 當設置一個動畫背景一個ActionBar,總是確保盡可能是微妙的。動畫不應干擾或中斷用戶在他/她與你的應用程序的交互,比如你可以運行動畫只有當用戶不觸及你的活動。      使用本文中描述的技術力量系統失效整個ActionBarContainer對於每個動畫幀。減少你的動畫的持續時間盡可能多的CPU和GPU消費

動畫背景可拉的不應該是一些必要的程序。可拉的只能作為樣式組件而不是交互組件。

我可以寫一整本書的章可拉的概念。把簡單,當設置繪圖作為一個視圖的背景,視圖注冊自己是可拉的的回調。這讓繪圖視圖無效它屬於。換句話說,它允許您創建畫板,可以刷新/重畫自己。Android還將有專家說它讓你輕易洩露上下文保持靜態引用時一個繪圖。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved