百叶窗视图自定义视图添加到动态壁纸

时间:2014-08-16 03:40:44

标签: android live-wallpaper

有没有办法可以将索尼的blindsview添加到动态壁纸中?

这是一个自定义视图,代码是

package com.sahaab.ui.BlindsView;

import java.util.ArrayList;

import com.sahaab.ui.BlindsView.R;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LightingColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;

public class BlindsView extends LinearLayout {

    // Config
    private static final boolean LOG_ON = true;
    private static String LOG_TAG; // assigned in init
    private static final float CONFIG_MAX_ROTATIONX = 45f;
    private static final float CONFIG_MAX_ROTATIONY = 15f;
    private static final float CONFIG_CAMERA_DISTANCE_Z = -35;
    private static float mMaxAffectRadius;
    private static final float CONFIG_MIN_SCALING = 0.97f;
    private static final float CONFIG_MAX_YOFFSET = 16;
    private static final int CONFIG_BLINDSTROKE_BASECOLOR = Color.DKGRAY;
    private static final int CONFIG_BLINDSTROKE_ALPHA = 175;
    private static final int CONFIG_BLINDSTROKE_BEVEL_ANGLE = 45;
    private static float mConfigStrokeWidth;

    // Drawing tools
    private Bitmap mUndistortedBitmap;
    private Canvas mUndistortedCanvas;
    private BitmapDrawable mBgDrawable;
    private Paint mBlindPaint, mBlindStrokePaint;
    private final Camera mCamera = new Camera();

    // State
    private ArrayList<BlindInfo> mBlindSet = null;
    private boolean mIsInBlindMode = false;

    public BlindsView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();

    }

    public BlindsView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public BlindsView(Context context) {
        super(context);
        init();
    }

    //
    // View and ViewGroup duties and overrides:
    /**
     * Called by draw to draw the child views. This may be overridden by derived
     * classes to gain control just before its children are drawn (but after its
     * own view has been drawn).
     */
    @Override
    protected void dispatchDraw(Canvas canvas) {
        if (LOG_ON) {
            Log.d(LOG_TAG,
                    "dispatchDraw     (dispatching draw calls to all children)");
        }
        drawCustomStuff(canvas);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        setupBlinds((int) getResources().getDimension(R.dimen.blindHeight));
        if (LOG_ON) {
            Log.d(LOG_TAG,
                    "onLayout. Layout properties changed - blinds set rebuilt. New set contains "
                            + mBlindSet.size() + " blinds");
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_MOVE:
            mIsInBlindMode = true;
            calculateBlindRotations(event.getX(), event.getY());
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            mIsInBlindMode = false;
            break;
        default:
            // no change
            break;

        }
        invalidate();
        return true;
    }

    //
    // Internal convenience methods:

    /**
     * Constructor addition
     */
    public void init() {
        LOG_TAG = this.getClass().getSimpleName();

        mBlindPaint = new Paint();
        mBlindPaint.setStyle(Paint.Style.FILL);
        mBlindPaint.setAntiAlias(true);
        mBlindPaint.setFilterBitmap(true);

        mConfigStrokeWidth = getResources().getDimension(
                R.dimen.blindStrokeWidth);
        mBlindStrokePaint = new Paint();
        mBlindStrokePaint.setColor(CONFIG_BLINDSTROKE_BASECOLOR);
        mBlindStrokePaint.setAlpha(CONFIG_BLINDSTROKE_ALPHA);
        mBlindStrokePaint.setStrokeWidth(mConfigStrokeWidth);
        mBlindStrokePaint.setAntiAlias(true);
        mBlindStrokePaint.setFilterBitmap(true);

        mMaxAffectRadius = getResources().getDimension(
                R.dimen.touchEffectRadius);
    }

    private void drawCustomStuff(Canvas screenCanvas) {
        if (LOG_ON) {
            Log.d(LOG_TAG,
                    "drawCustomStuff  (doing the custom drawing of this ViewGroup)");
        }

        final boolean initBmpAndCanvas = (mIsInBlindMode && (!(mUndistortedBitmap != null && !mUndistortedBitmap
                .isRecycled())));

        if (!mIsInBlindMode || (mIsInBlindMode && initBmpAndCanvas)) {
            // Draw normally
            if (mIsInBlindMode && initBmpAndCanvas) {
                mUndistortedBitmap = Bitmap.createBitmap(getWidth(),
                        getHeight(), Bitmap.Config.ARGB_8888);
                mUndistortedCanvas = new Canvas(mUndistortedBitmap);
            }

            Canvas canvasToDrawTo = mIsInBlindMode ? mUndistortedCanvas
                    : screenCanvas;

            drawUndistorted(canvasToDrawTo);
        }
        if (mIsInBlindMode) {
            // Draw blinds version
            drawBlinds(screenCanvas);
        }
    }

    private void drawUndistorted(Canvas canvas) {
        if (mBgDrawable != null) {
            mBgDrawable.draw(canvas);
        }
        super.dispatchDraw(canvas);
    }

    private void drawBlinds(Canvas canvas) {
        // Draw each blind in order, starting from the top one.
        for (BlindInfo blind : mBlindSet) {
            drawBlind(blind, canvas);
        }
    }

    private void drawBlind(BlindInfo info, Canvas canvas) {
        // Read params
        final int width = info.getWidth();
        final int height = info.getHeight();
        final int coordX = info.getLeft();
        final int coordY = info.getTop();
        final float xRotation = info.getRotationX();
        final float yRotation = info.getRotationY();
        final float zRotation = info.getRotationZ();
        final float scale = info.getScale();
        final float yOffset = info.getYoffset();
        final boolean drawBottomStroke = info.getDrawStroke();

        // Prepare Canvas and Camera
        canvas.save();
        mCamera.save();
        mCamera.setLocation(0, 0, CONFIG_CAMERA_DISTANCE_Z);
        canvas.translate((coordX + (width / 2f)), (coordY + (height / 2f)));

        // Apply transformations
        mCamera.rotateY(yRotation);
        mCamera.rotateX(xRotation);
        canvas.scale(scale, scale, 0f, 0f);
        canvas.translate(0f, yOffset);

        Matrix cameraMatrix = new Matrix();
        mCamera.getMatrix(cameraMatrix);
        canvas.concat(cameraMatrix);

        mBlindPaint.setColorFilter(calculateLight(xRotation));

        // Draw
        final Rect src = new Rect(coordX, coordY, (coordX + width),
                (coordY + height));
        final RectF dst = new RectF(-(width / 2f), -(height / 2f), width / 2f,
                height / 2f);
        canvas.drawBitmap(mUndistortedBitmap, src, dst, mBlindPaint);
        if (drawBottomStroke) {
            mBlindStrokePaint.setColorFilter(calculateLight(xRotation
                    + CONFIG_BLINDSTROKE_BEVEL_ANGLE));
            canvas.drawLine(dst.left, (dst.bottom - mConfigStrokeWidth / 2f),
                    dst.right, (dst.bottom - mConfigStrokeWidth / 2f),
                    mBlindStrokePaint);
        }

        // Restore Canvas and Camera
        mCamera.restore();
        canvas.restore();

        if (LOG_ON) {
            Log.d(LOG_TAG, "Drew blind with size " + width + " by " + height
                    + " px with rotation (" + xRotation + ", " + yRotation
                    + ", " + zRotation + ") (x,y,z) at coordinates " + coordX
                    + ", " + coordY);
        }
    }

    /**
     * Creates a new Blinds set, given a blind height. Requires the BlindsView
     * to be measure and have an assigned width and height.
     * 
     * @param blindHeight
     *            in dip
     * @param bvHeight
     *            in dip
     * @param bvWidth
     *            in dip
     */
    private void setupBlinds(int blindHeight) {

        if (blindHeight == 0) {
            throw new IllegalArgumentException("baseHeight must be >0");
        }

        ArrayList<BlindInfo> bi = new ArrayList<BlindInfo>();
        int accumulatedHeight = 0;
        do {
            bi.add(new BlindInfo(0, accumulatedHeight, getWidth(),
                    accumulatedHeight + blindHeight));
            accumulatedHeight += blindHeight;
        } while (accumulatedHeight < getHeight());

        mBlindSet = bi;
    }

    private synchronized void calculateBlindRotations(float xPos, float yPos) {

        float currentBlindPivotY;
        float normalizedVerticalDistanceFromTouch;

        for (BlindInfo currentBlind : mBlindSet) {
            currentBlindPivotY = currentBlind.getTop()
                    + (float) currentBlind.getHeight() / 2f;

            normalizedVerticalDistanceFromTouch = Math
                    .abs((yPos - currentBlindPivotY) / mMaxAffectRadius);

            float xRotation = 0;
            float yRotation = 0;
            float scaling = 1f;
            float yOffset = 0f;
            boolean drawStroke = false;
            // Only rotate if within valid range
            if (normalizedVerticalDistanceFromTouch <= 1f) {

                // X AXIS ROTATION:
                // rot(d) = -((d-0.55)*2)^2+1 where 0<=d
                final double normalizedRotationX = Math
                        .max(0d,
                                (-Math.pow(
                                        ((normalizedVerticalDistanceFromTouch - 0.55f) * 2f),
                                        2) + 1));

                // Blind above touch means negative angle
                if ((currentBlindPivotY < yPos)) {
                    xRotation = (float) -(CONFIG_MAX_ROTATIONX * normalizedRotationX);
                } else {
                    xRotation = (float) (CONFIG_MAX_ROTATIONX * normalizedRotationX);
                }

                // Y AXIS ROTATION:
                // -1 <= normalizedHorizontalDistanceFromPivot <= 1
                final float normalizedHorizontalDistanceFromPivot = ((xPos / getWidth()) - 0.5f) / 0.5f;
                // 0 <= linearDeclineFactor <= 1
                final float linearDeclineFactor = 1 - normalizedVerticalDistanceFromTouch;
                yRotation = CONFIG_MAX_ROTATIONY
                        * normalizedHorizontalDistanceFromPivot
                        * linearDeclineFactor;

                // SCALING:
                // 1 at both end points, CONFIG_MIN_SCALING at center and
                // declining with the squared distance in between.
                scaling = 1f
                        - (1f - normalizedVerticalDistanceFromTouch
                                * normalizedVerticalDistanceFromTouch)
                        * (1f - CONFIG_MIN_SCALING);

                // Y OFFSET:
                yOffset = ((1f - normalizedVerticalDistanceFromTouch
                        * normalizedVerticalDistanceFromTouch))
                        * CONFIG_MAX_YOFFSET;

                // SET STROKE DRAWING
                drawStroke = true;

            }
            currentBlind.setRotations(xRotation, yRotation, 0f);
            currentBlind.setScale(scaling);
            currentBlind.setYoffset(yOffset);
            currentBlind.setDrawStroke(drawStroke);
        }

    }

    // Lighting effect shamelessly nicked from Anders:
    // http://developer.sonymobile.com/wp/2010/05/31/android-tutorial-making-your-own-3d-list-part-2/
    // "Let there be light"
    /** Ambient light intensity */
    private static final int AMBIENT_LIGHT = 55;

    /** Diffuse light intensity */
    private static final int DIFFUSE_LIGHT = 255;

    /** Specular light intensity */
    private static final float SPECULAR_LIGHT = 70;

    /** Shininess constant */
    private static final float SHININESS = 255;

    /** The max intensity of the light */
    private static final int MAX_INTENSITY = 0xFF;

    /** Light source angular offset */
    private static final float LIGHT_SOURCE_ANGLE = 38f;

    private LightingColorFilter calculateLight(float rotation) {
        rotation -= LIGHT_SOURCE_ANGLE;
        final double cosRotation = Math.cos(Math.PI * rotation / 180);
        int intensity = AMBIENT_LIGHT + (int) (DIFFUSE_LIGHT * cosRotation);
        int highlightIntensity = (int) (SPECULAR_LIGHT * Math.pow(cosRotation,
                SHININESS));

        if (intensity > MAX_INTENSITY) {
            intensity = MAX_INTENSITY;
        }
        if (highlightIntensity > MAX_INTENSITY) {
            highlightIntensity = MAX_INTENSITY;
        }

        final int light = Color.rgb(intensity, intensity, intensity);
        final int highlight = Color.rgb(highlightIntensity, highlightIntensity,
                highlightIntensity);

        return new LightingColorFilter(light, highlight);
    }

    //
    // Public interface
    public void setBackground(int id) {
        mBgDrawable = (BitmapDrawable) getResources().getDrawable(id);
        centerBgDrawable();
    }

    @Override
    public void setBackground(Drawable background) {
        mBgDrawable = (BitmapDrawable) background;
        centerBgDrawable();
    }

    private void centerBgDrawable() {
        if (mBgDrawable != null) {
            final DisplayMetrics dm = getResources().getDisplayMetrics();
            mBgDrawable.setTargetDensity(dm);
            mBgDrawable.setGravity(android.view.Gravity.CENTER);
            mBgDrawable.setBounds(0, 0, dm.widthPixels, dm.heightPixels);
        }
        postInvalidate();
    }

}

如何设置我的动态壁纸服务才能包含此视图? 目前将其添加到活动中,这就是我做的事情

<com.sahaab.ui.BlindsView.BlindsView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/blindsview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:paddingTop="15dp" >

        <Button
            android:id="@+id/setWallpaper_button"
            style="?android:attr/buttonStyleSmall"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/dummy_button_one" />

</com.sahaab.ui.BlindsView.BlindsView>

有没有办法可以为livewallpaper或其他东西制作布局?日Thnx

1 个答案:

答案 0 :(得分:0)

要诚实,这很难。但是有办法。 WallpaperService.Engine中最重要的是Canvas。所以你可以画很多东西。您无法绘制布局(视图),但可以绘制位图。 我们可以通过View.buildDrawingCache(),View.getDrawingCache()来获取Bitmap。