`
duoerbasilu
  • 浏览: 1482012 次
文章分类
社区版块
存档分类
最新评论

Android 自带Apps 学习---Live Wallpaper

 
阅读更多

1:配置Mainfest.xml

Android可查到该Live Wallpaper

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.wing.wallpaper.test"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="4" />
    <!-- Android 会通过android.software.live_wallpaper feature Intent 获取动态壁纸列表 -->
  <uses-feature android:name="android.software.live_wallpaper" />
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".TestWallpaper"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:label="@string/clock_settings"
            android:name="com.android.wallpaper.polarclock.PolarClockSettings"
            android:theme="@android:style/Theme"
            android:exported="true">
        </activity>
        
        <!--android:permission="android.permission.BIND_WALLPAPER" 绑定壁纸权限 -->
        <!--<action android:name="android.service.wallpaper.WallpaperService" 动态壁纸主View Layout -->
        <!--  <meta-data android:name="android.service.wallpaper" android:resource="@xml/polar_clock" /> Wallpaper 相关配置 -->
        <service
            android:label="@string/wallpaper_clock"
            android:name="com.android.wallpaper.polarclock.PolarClockWallpaper"
            android:permission="android.permission.BIND_WALLPAPER">
            <intent-filter>
                <action android:name="android.service.wallpaper.WallpaperService" />
            </intent-filter>
            <meta-data android:name="android.service.wallpaper" android:resource="@xml/polar_clock" />
        </service>
    </application>
</manifest>

Wallpaper 相关配置xml/polar_clock.xml

<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
    android:author="@string/wallpaper_clock_author"
    android:description="@string/wallpaper_clock_desc"
    android:thumbnail="@drawable/polarclock_thumb"
    android:settingsActivity="com.android.wallpaper.polarclock.PolarClockSettings" />

Wallpaper 作者,缩略图,设置Activity

2: 创建Setting Activity

public class PolarClockSettings extends WallpaperSettingsActivity
    implements SharedPreferences.OnSharedPreferenceChangeListener {

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        //定义SharedPreferencesName,可通过该Name对其修改时间注册监听,见下
        getPreferenceManager().setSharedPreferencesName(
                PolarClockWallpaper.SHARED_PREFS_NAME);
        addPreferencesFromResource(R.xml.polar_clock_prefs);
        getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(
                this);
    }

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

    @Override
    protected void onDestroy() {
        getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
                this);
        super.onDestroy();
    }

    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
            String key) {
        (new BackupManager(this)).dataChanged();
    }
}

Setting Activity 配置 xml/R.xml.polar_clock_prefs

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
        android:title="@string/clock_settings"
        android:key="polar_clock_settings">

    <CheckBoxPreference
            android:key="show_seconds"
            android:title="@string/show_seconds"
            android:defaultValue="true"
            android:persistent="true"
            />
    <CheckBoxPreference
            android:key="variable_line_width"
            android:title="@string/variable_line_width"
            android:defaultValue="true"
            android:persistent="true"
            />
    <ListPreference
            android:key="palette"
            android:title="@string/palette"
            android:entries="@array/polar_clock_palette_names"
            android:entryValues="@array/polar_clock_palette_ids"
            />
</PreferenceScreen>

3: Wallpaper 主View

public class PolarClockWallpaper extends WallpaperService {
    private final Handler mHandler = new Handler();

    private IntentFilter mFilter;

    @Override
    public void onCreate() {
        super.onCreate();

        mFilter = new IntentFilter();
        mFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    public Engine onCreateEngine() {
        return new ClockEngine();
    }
    class ClockEngine extends Engine implements SharedPreferences.OnSharedPreferenceChangeListener {
        private static final float SMALL_RING_THICKNESS = 8.0f;
        private static final float MEDIUM_RING_THICKNESS = 16.0f;
        private static final float LARGE_RING_THICKNESS = 32.0f;

        private static final float DEFAULT_RING_THICKNESS = 24.0f;

        private static final float SMALL_GAP = 14.0f;
        private static final float LARGE_GAP = 38.0f;

        private final HashMap<String, ClockPalette> mPalettes = new HashMap<String, ClockPalette>();
        private ClockPalette mPalette;

        private SharedPreferences mPrefs;
        private boolean mShowSeconds;
        private boolean mVariableLineWidth;

        private boolean mWatcherRegistered;
        private Time mCalendar;

        private final Paint mPaint = new Paint();
        private final RectF mRect = new RectF();

        private float mOffsetX;

        private final BroadcastReceiver mWatcher = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                final String timeZone = intent.getStringExtra("time-zone");
                mCalendar = new Time(TimeZone.getTimeZone(timeZone).getID());
                drawFrame();
            }
        };

        private final Runnable mDrawClock = new Runnable() {
            public void run() {
                drawFrame();
            }
        };
        private boolean mVisible;

        ClockEngine() {
        	//android 自带xml解析工具
            XmlResourceParser xrp = getResources().getXml(R.xml.polar_clock_palettes);
            try {
                int what = xrp.getEventType();
                while (what != END_DOCUMENT) {
                    if (what == START_TAG) {
                        if ("palette".equals(xrp.getName())) {
                            ClockPalette pal = ClockPalette.parseXmlPaletteTag(xrp);
                            if (pal.getId() != null) {
                                mPalettes.put(pal.getId(), pal);
                            }
                        }
                    }
                    what = xrp.next();
                }
            } catch (IOException e) {
                Log.e(LOG_TAG, "An error occured during wallpaper configuration:", e);
            } catch (XmlPullParserException e) {
                Log.e(LOG_TAG, "An error occured during wallpaper configuration:", e);
            } finally {
                xrp.close();
            }

            mPalette = CyclingClockPalette.getFallback();
        }

        @Override
        public void onCreate(SurfaceHolder surfaceHolder) {
            super.onCreate(surfaceHolder);
 
            //对setting的SharedPreferences 注册修改监听
            mPrefs = PolarClockWallpaper.this.getSharedPreferences(SHARED_PREFS_NAME, 0);
            mPrefs.registerOnSharedPreferenceChangeListener(this);

            // load up user's settings 加载SharedPreferences
            onSharedPreferenceChanged(mPrefs, null);

            mCalendar = new Time();
            mCalendar.setToNow();

            final Paint paint = mPaint;
            paint.setAntiAlias(true);
            paint.setStrokeWidth(DEFAULT_RING_THICKNESS);
            paint.setStrokeCap(Paint.Cap.ROUND);
            paint.setStyle(Paint.Style.STROKE);

            if (isPreview()) {
                mOffsetX = 0.5f;            
            }
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            //取消对时区改变的坚挺
            if (mWatcherRegistered) {
                mWatcherRegistered = false;
                unregisterReceiver(mWatcher);
            }
            //取消图像重绘事件队列
            mHandler.removeCallbacks(mDrawClock);
        }
        //特定SharedPreferences 配置改变回调方法
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
                String key) {

            boolean changed = false;
            if (key == null || PREF_SHOW_SECONDS.equals(key)) {
                mShowSeconds = sharedPreferences.getBoolean(
                    PREF_SHOW_SECONDS, true);
                changed = true;
            }
            if (key == null || PREF_VARIABLE_LINE_WIDTH.equals(key)) {
                mVariableLineWidth = sharedPreferences.getBoolean(
                    PREF_VARIABLE_LINE_WIDTH, true);
                changed = true;
            }
            if (key == null || PREF_PALETTE.equals(key)) {
                String paletteId = sharedPreferences.getString(
                    PREF_PALETTE, "");
                ClockPalette pal = mPalettes.get(paletteId);
                if (pal != null) {
                    mPalette = pal;
                    changed = true;
                }
            }

            if (mVisible && changed) {
                drawFrame();
            }
        }
//View 是否可见变化响应时间
        @Override
        public void onVisibilityChanged(boolean visible) {
            mVisible = visible;
            if (visible) {
                if (!mWatcherRegistered) {
                    mWatcherRegistered = true;
                    registerReceiver(mWatcher, mFilter, null, mHandler);
                }
                mCalendar = new Time();
                mCalendar.setToNow();
            } else {
                if (mWatcherRegistered) {
                    mWatcherRegistered = false;
                    unregisterReceiver(mWatcher);
                }
                mHandler.removeCallbacks(mDrawClock);
            }
            drawFrame();
        }
      //View 大小发生改变
        @Override
        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            super.onSurfaceChanged(holder, format, width, height);
            drawFrame();
        }

        @Override
        public void onSurfaceCreated(SurfaceHolder holder) {
            super.onSurfaceCreated(holder);
        }

        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder) {
            super.onSurfaceDestroyed(holder);
            mVisible = false;
            mHandler.removeCallbacks(mDrawClock);
        }
        //位置改变,如Home滑动到别的页,3->1->3
        @Override
        public void onOffsetsChanged(float xOffset, float yOffset,
                float xStep, float yStep, int xPixels, int yPixels) {
            if (isPreview()) return;

            mOffsetX = xOffset;
            drawFrame();
        }
        //绘制view
        void drawFrame() {
            if (mPalette == null) {
                Log.w("PolarClockWallpaper", "no palette?!");
                return;
            }

            final SurfaceHolder holder = getSurfaceHolder();
            final Rect frame = holder.getSurfaceFrame();
            final int width = frame.width();
            final int height = frame.height();

            Canvas c = null;
            try {
                c = holder.lockCanvas();
                if (c != null) {
                    final Time calendar = mCalendar;
                    final Paint paint = mPaint;

                    final long millis = System.currentTimeMillis();
                    calendar.set(millis);
                    calendar.normalize(false);

                    int s = width / 2;
                    int t = height / 2;

                    c.drawColor(mPalette.getBackgroundColor());

                    c.translate(s + MathUtils.lerp(s, -s, mOffsetX), t);
                    c.rotate(-90.0f);
                    if (height < width) {
                        c.scale(0.9f, 0.9f);
                    }

                    float size = Math.min(width, height) * 0.5f - DEFAULT_RING_THICKNESS;
                    final RectF rect = mRect;
                    rect.set(-size, -size, size, size);
                    float angle;

                    float lastRingThickness = DEFAULT_RING_THICKNESS;

                    if (mShowSeconds) {
                        // Draw seconds  
                        angle = (float) (millis % 60000) / 60000.0f;
                        //Log.d("PolarClock", "millis=" + millis + ", angle=" + angle);
                        paint.setColor(mPalette.getSecondColor(angle));

                        if (mVariableLineWidth) {
                            lastRingThickness = SMALL_RING_THICKNESS;
                            paint.setStrokeWidth(lastRingThickness);
                        }
                        c.drawArc(rect, 0.0f, angle * 360.0f, false, paint);
                    }

                    // Draw minutes
                    size -= (SMALL_GAP + lastRingThickness);
                    rect.set(-size, -size, size, size);

                    angle = ((calendar.minute * 60.0f + calendar.second) % 3600) / 3600.0f;
                    paint.setColor(mPalette.getMinuteColor(angle));

                    if (mVariableLineWidth) {
                        lastRingThickness = MEDIUM_RING_THICKNESS;
                        paint.setStrokeWidth(lastRingThickness);
                    }
                    c.drawArc(rect, 0.0f, angle * 360.0f, false, paint);

                    // Draw hours
                    size -= (SMALL_GAP + lastRingThickness);
                    rect.set(-size, -size, size, size);

                    angle = ((calendar.hour * 60.0f + calendar.minute) % 1440) / 1440.0f;
                    paint.setColor(mPalette.getHourColor(angle));

                    if (mVariableLineWidth) {
                        lastRingThickness = LARGE_RING_THICKNESS;
                        paint.setStrokeWidth(lastRingThickness);
                    }
                    c.drawArc(rect, 0.0f, angle * 360.0f, false, paint);

                    // Draw day
                    size -= (LARGE_GAP + lastRingThickness);
                    rect.set(-size, -size, size, size);

                    angle = (calendar.monthDay - 1) /
                            (float) (calendar.getActualMaximum(Time.MONTH_DAY) - 1);
                    paint.setColor(mPalette.getDayColor(angle));

                    if (mVariableLineWidth) {
                        lastRingThickness = MEDIUM_RING_THICKNESS;
                        paint.setStrokeWidth(lastRingThickness);
                    }
                    c.drawArc(rect, 0.0f, angle * 360.0f, false, paint);

                    // Draw month
                    size -= (SMALL_GAP + lastRingThickness);
                    rect.set(-size, -size, size, size);

                    angle = (calendar.month) / 11.0f; // NB: month is already on [0..11]

                    paint.setColor(mPalette.getMonthColor(angle));

                    if (mVariableLineWidth) {
                        lastRingThickness = LARGE_RING_THICKNESS;
                        paint.setStrokeWidth(lastRingThickness);
                    }
                    c.drawArc(rect, 0.0f, angle * 360.0f, false, paint);
                }
            } finally {
                if (c != null) holder.unlockCanvasAndPost(c);
            }

            mHandler.removeCallbacks(mDrawClock);
            if (mVisible) {
                if (mShowSeconds) {
                    mHandler.postDelayed(mDrawClock, 1000 / 25);
                } else {
                    // If we aren't showing seconds, we don't need to update
                    // nearly as often.
                    mHandler.postDelayed(mDrawClock, 2000);
                }
            }
        }
    }


其他相关类

// Clock 父类
    static abstract class ClockPalette {
        public static ClockPalette parseXmlPaletteTag(XmlResourceParser xrp) {
            String kind = xrp.getAttributeValue(null, "kind");
            if ("cycling".equals(kind)) {
                return CyclingClockPalette.parseXmlPaletteTag(xrp);
            } else {
                return FixedClockPalette.parseXmlPaletteTag(xrp);
            }
        }

        public abstract int getBackgroundColor();

        // forAngle should be on [0.0,1.0) but 1.0 must be tolerated
        public abstract int getSecondColor(float forAngle);

        public abstract int getMinuteColor(float forAngle);

        public abstract int getHourColor(float forAngle);

        public abstract int getDayColor(float forAngle);

        public abstract int getMonthColor(float forAngle);

        public abstract String getId();

    }

    static class FixedClockPalette extends ClockPalette {
        protected String mId;
        protected int mBackgroundColor;
        protected int mSecondColor;
        protected int mMinuteColor;
        protected int mHourColor;
        protected int mDayColor;
        protected int mMonthColor;

        private static FixedClockPalette sFallbackPalette = null;

        public static FixedClockPalette getFallback() {
            if (sFallbackPalette == null) {
                sFallbackPalette = new FixedClockPalette();
                sFallbackPalette.mId = "default";
                sFallbackPalette.mBackgroundColor = Color.WHITE;
                sFallbackPalette.mSecondColor =
                    sFallbackPalette.mMinuteColor =
                    sFallbackPalette.mHourColor =
                    sFallbackPalette.mDayColor =
                    sFallbackPalette.mMonthColor =
                    Color.BLACK;
            }
            return sFallbackPalette;
        }

        private FixedClockPalette() { }

        public static ClockPalette parseXmlPaletteTag(XmlResourceParser xrp) {
            final FixedClockPalette pal = new FixedClockPalette();
            pal.mId = xrp.getAttributeValue(null, "id");
            String val;
            if ((val = xrp.getAttributeValue(null, "background")) != null)
                pal.mBackgroundColor = Color.parseColor(val);
            if ((val = xrp.getAttributeValue(null, "second")) != null)
                pal.mSecondColor = Color.parseColor(val);
            if ((val = xrp.getAttributeValue(null, "minute")) != null)
                pal.mMinuteColor = Color.parseColor(val);
            if ((val = xrp.getAttributeValue(null, "hour")) != null)
                pal.mHourColor = Color.parseColor(val);
            if ((val = xrp.getAttributeValue(null, "day")) != null)
                pal.mDayColor = Color.parseColor(val);
            if ((val = xrp.getAttributeValue(null, "month")) != null)
                pal.mMonthColor = Color.parseColor(val);
            return (pal.mId == null) ? null : pal;
        }

        @Override
        public int getBackgroundColor() {
            return mBackgroundColor;
        }

        @Override
        public int getSecondColor(float forAngle) {
            return mSecondColor;
        }

        @Override
        public int getMinuteColor(float forAngle) {
            return mMinuteColor;
        }

        @Override
        public int getHourColor(float forAngle) {
            return mHourColor;
        }

        @Override
        public int getDayColor(float forAngle) {
            return mDayColor;
        }

        @Override
        public int getMonthColor(float forAngle) {
            return mMonthColor;
        }

        @Override
        public String getId() {
            return mId;
        }

    }

    static class CyclingClockPalette extends ClockPalette {
        protected String mId;
        protected int mBackgroundColor;
        protected float mSaturation;
        protected float mBrightness;

        private static final int COLORS_CACHE_COUNT = 720;
        private final int[] mColors = new int[COLORS_CACHE_COUNT];

        private static CyclingClockPalette sFallbackPalette = null;

        public static CyclingClockPalette getFallback() {
            if (sFallbackPalette == null) {
                sFallbackPalette = new CyclingClockPalette();
                sFallbackPalette.mId = "default_c";
                sFallbackPalette.mBackgroundColor = Color.WHITE;
                sFallbackPalette.mSaturation = 0.8f;
                sFallbackPalette.mBrightness = 0.9f;
                sFallbackPalette.computeIntermediateColors();
            }
            return sFallbackPalette;
        }

        private CyclingClockPalette() { }

        private void computeIntermediateColors() {
            final int[] colors = mColors;
            final int count = colors.length;
            float invCount = 1.0f / (float) COLORS_CACHE_COUNT;
            for (int i = 0; i < count; i++) {
                colors[i] = Color.HSBtoColor(i * invCount, mSaturation, mBrightness);
            }
        }

        public static ClockPalette parseXmlPaletteTag(XmlResourceParser xrp) {
            final CyclingClockPalette pal = new CyclingClockPalette();
            pal.mId = xrp.getAttributeValue(null, "id");
            String val;
            if ((val = xrp.getAttributeValue(null, "background")) != null)
                pal.mBackgroundColor = Color.parseColor(val);
            if ((val = xrp.getAttributeValue(null, "saturation")) != null)
                pal.mSaturation = Float.parseFloat(val);
            if ((val = xrp.getAttributeValue(null, "brightness")) != null)
                pal.mBrightness = Float.parseFloat(val);
            if (pal.mId == null) {
                return null;
            } else {
                pal.computeIntermediateColors();
                return pal;
            }
        }
        @Override
        public int getBackgroundColor() {
            return mBackgroundColor;
        }

        @Override
        public int getSecondColor(float forAngle) {
            if (forAngle >= 1.0f || forAngle < 0.0f) forAngle = 0.0f;
            return mColors[((int) (forAngle * COLORS_CACHE_COUNT))];
        }

        @Override
        public int getMinuteColor(float forAngle) {
            if (forAngle >= 1.0f || forAngle < 0.0f) forAngle = 0.0f;
            return mColors[((int) (forAngle * COLORS_CACHE_COUNT))];
        }

        @Override
        public int getHourColor(float forAngle) {
            if (forAngle >= 1.0f || forAngle < 0.0f) forAngle = 0.0f;
            return mColors[((int) (forAngle * COLORS_CACHE_COUNT))];
        }

        @Override
        public int getDayColor(float forAngle) {
            if (forAngle >= 1.0f || forAngle < 0.0f) forAngle = 0.0f;
            return mColors[((int) (forAngle * COLORS_CACHE_COUNT))];
        }

        @Override
        public int getMonthColor(float forAngle) {
            if (forAngle >= 1.0f || forAngle < 0.0f) forAngle = 0.0f;
            return mColors[((int) (forAngle * COLORS_CACHE_COUNT))];
        }

        @Override
        public String getId() {
            return mId;
        }
    }


配置ClockDelete 的xml

/xml/polar_clock_palettes

<?xml version="1.0" encoding="utf-8"?>

<palettes>
  <!-- basic white polar clock with color-cycling rings -->
  <palette kind="cycling"
    id="palette_white_c"
    background="#FFFFFFFF"
    saturation="0.8" brightness="0.9" />
  <!-- same as above, but on black -->
  <palette kind="cycling"
    id="palette_black_c"
    background="#FF000000"
    saturation="1.0" brightness="0" />
  <!-- a nice gray color scheme with an orange seconds ring -->
  <palette kind="fixed"
    id="palette_gray"
    background="#FF555555"
    second="#FFCC8800" minute="#FF333333" hour="#FF000000"
    day="#FF999999" month="#FF777777" />
  <!-- smooth black with a purple cast -->
  <palette kind="fixed"
    id="palette_violet"
    background="#FF181020"
    second="#FF602070" minute="#603050" hour="#FF040008"
    day="#FF706080" month="#FF403050" />
  <!-- green on black -->
  <palette kind="fixed"
    id="palette_matrix"
    background="#FF002200"
    second="#FF00FF00" minute="#FF00BB00" hour="#FF007700"
    day="#FF00AA00" month="#FF006600" />
  <!-- orange -->
  <palette kind="fixed"
    id="palette_halloween"
    background="#FF884400"
    second="#FFFFFF00" minute="#FFFF8800" hour="#FFFF8800"
    day="#FF000000" month="#FF000000" />
  <!-- based on Zenburn by Jani Nurminen -->
  <palette kind="fixed"
    id="palette_zenburn"
    background="#FF3f3f3f"
    second="#FF8aCCCF" minute="#FFCB9292" hour="#FFCCDC90"
    day="#FFDCA3A3" month="#FF7f9f7f" />
  <!-- electric blue -->
  <palette kind="fixed"
    id="palette_oceanic"
    background="#FF000066"
    second="#FF6666FF" minute="#FF0000FF" hour="#FF0000AA"
    day="#FF000033" month="#FF000011" />
</palettes>




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics