在自定义安卓模拟手中进行缩放和对齐

时间:2014-08-13 21:03:03

标签: java android scaling clock

我搜索了这个主题好几天了,但终于搞糊涂了。我们的想法是创建自己的警报应用程序与一些特殊的技巧。首先,我需要时钟指针。为了创建自定义时钟,我使用了自己的类,它扩展了View。时针和分针是PNG图像。 它们应该位于屏幕的中心,但它们不应该。实际上,我甚至看不到它们。这就是问题所在。

这是Clock类

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
//import android.os.Handler;
import android.text.format.Time;
import android.util.AttributeSet;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;



@SuppressLint("NewApi")
public class Clock extends View {

public Clock(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
}


private Drawable mHourHand;
private Drawable mMinuteHand;

private boolean mAttached;

static private float mMinutes;
static private float mHour;
private boolean mChanged;

Context mContext;
private boolean mSeconds;

// Gettes & setters. These clock must present alarm time which user sets in the next view

protected float getmMinutes() {
return mMinutes;
}

protected static void setmMinutes(float mMinutes) {
Clock.mMinutes = mMinutes;
}

protected float getmHour() {
return mHour;
}

protected static void setmHour(float mHour) {
Clock.mHour = mHour;
}


private Point size;

// ctors

public Clock(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}


public Clock(Context context, AttributeSet attrs,
        int defStyle) {
        super(context, attrs, defStyle);
        Resources r = context.getResources();
        TypedArray a =
        context.obtainStyledAttributes(attrs, R.styleable.AnalogClock, defStyle, 0);
        mContext=context;

        mHourHand = r.getDrawable(R.drawable.hours);

        mMinuteHand = r.getDrawable(R.drawable.minuts);
}



@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();

    if (!mAttached) {
        mAttached = true;
        IntentFilter filter = new IntentFilter();

        filter.addAction(Intent.ACTION_TIME_TICK);
        filter.addAction(Intent.ACTION_TIME_CHANGED);
        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);

     // getContext().registerReceiver(mIntentReceiver, filter, null, mHandler);
    }

 }

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {


    int desiredWidth = 150;  // and yes, 150 what? px, inches, dpi-s? I draw it just randomly
    int desiredHeight = 150;

    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    int width;
    int height;

    //Measure Width
    if (widthMode == MeasureSpec.EXACTLY) {
        //Must be this size
        width = widthSize;
    } else if (widthMode == MeasureSpec.AT_MOST) {
        //Can't be bigger than...
        width = Math.min(desiredWidth, widthSize);
    } else {
        //Be whatever you want
        width = desiredWidth;
    }

    //Measure Height
    if (heightMode == MeasureSpec.EXACTLY) {
        //Must be this size
        height = heightSize;
    } else if (heightMode == MeasureSpec.AT_MOST) {
        //Can't be bigger than...
        height = Math.min(desiredHeight, heightSize);
    } else {
        //Be whatever you want
        height = desiredHeight;
    }

    setMeasuredDimension(width, height);

}


@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mChanged = true;
}




@SuppressWarnings({ "deprecation" })
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    boolean changed = mChanged;
    if (changed) {
        mChanged = false;
    }

    boolean seconds = mSeconds;
    if (seconds ) {
        mSeconds = false;
    }

    int w = 100;  //These are too made randomly
    int h = 100;  

    WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
   // if (android.os.Build.VERSION.SDK_INT <= 13)
   // {
        w = display.getWidth();  // deprecated
        h = display.getHeight();  // deprecated

    //}
   // else if (android.os.Build.VERSION.SDK_INT > 13)
    //{
        //size = null;
        //display.getSize(size);
        //w = size.x;
        //h = size.y;
    //}   ... I cant figure out, why, but size returns null. So I'll use deprecated ones just for     
     now.

    // **Here are my measures. I suggest that if height of an hour hand should be about 1/4 of   
       screen width, then following the proportion - width of that hand should be old width*new 
       height/old height, or smthng**   

    int sizeXHour = w/3;
        int sizeYHour = mHourHand.getIntrinsicHeight()*sizeXHour/mHourHand.getIntrinsicWidth();

        int xHour = sizeXHour/2;
        int yHour = sizeYHour/2;

        canvas.rotate(mHour / 12.0f * 360.0f, xHour, yHour);
        final Drawable hourHand = mHourHand;
        if (changed) {
        hourHand.setBounds((w / 2) - xHour, (h / 2) - yHour, sizeXHour, sizeYHour);
        }
        hourHand.draw(canvas);
        canvas.restore();

        int sizeYMinute = h/4;
        int sizeXMinute = mMinuteHand.getIntrinsicWidth()*sizeYMinute/mMinuteHand.getIntrinsicHeight();

        int xMinute = sizeXMinute/2;
        int yMinute = sizeYMinute/2;

        canvas.save();
        canvas.rotate(mMinutes / 60.0f * 360.0f, xMinute, yMinute);
        final Drawable minuteHand = mMinuteHand;
        if (changed) {
            minuteHand.setBounds((w / 2 - xMinute), (h / 2 - yMinute), sizeXMinute, sizeYMinute);
        }
        minuteHand.draw(canvas);
        canvas.restore();
        canvas.save();

}

我觉得有些事情是非常错误的,但无法想象什么。 XML是:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="ee.st.running.dreamyclock.MainActivity"
android:background = "@drawable/clockk" >

<View
    android:id="@+id/view1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

<st.running.dreamyclock.Clock
    android:id="@+id/clock"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical = "true"
    android:layout_marginTop="124dp" />
</RelativeLayout>
魅力是:

  <?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="AnalogClock">
    <attr name="hand_hour" format="reference"/>
    <attr name="hand_minute" format="reference"/>
</declare-styleable>
</resources>

它来自哪里?谢谢

1 个答案:

答案 0 :(得分:0)

这有用吗?尝试将其添加到Clock构造函数: setWillNotDraw(false);

&#34;如果此视图本身不进行任何绘制,请设置此标志以允许进一步优化。默认情况下,此标志未在View上设置,但可以在某些View子类(如ViewGroup)上设置。通常,如果你重写onDraw(android.graphics.Canvas),你应该清除这个标志。&#34;

编辑: 如果您想重新绘制视图,请调用invalidate()方法

&#34;使整个视图无效。如果视图可见,将在某个时间点调用onDraw(android.graphics.Canvas)。 &#34;

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mChanged = true;
    this.invalidate();
}

你甚至不必调用invalidate();如果您只是想旋转视图:

 @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mChanged = true;
        setRotation(20);
    }

编辑2:

当您为Drawable设置边界时,&#34;右边&#34;价值应高于&#34;左&#34;例如: minuteHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2) + 4, y + (h / 4)); 要么 minuteHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2) + minuteHand.getIntrinsicWidth(), y + (h / 4));