【问题标题】:Scale and align in custom android AnalogClock hands在自定义 android AnalogClock 指针中缩放和对齐
【发布时间】:2014-08-13 21:03:02
【问题描述】:

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

这是时钟类

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>

任何想法来自哪里?谢谢

【问题讨论】:

    标签: java android scaling clock


    【解决方案1】:

    这曾经有效吗?尝试将此添加到 Clock 构造函数: setWillNotDraw(false);

    "如果这个视图自己不做任何绘图,设置这个标志以允许进一步的优化。默认情况下,这个标志不在视图上设置,但可以在一些视图子类上设置,例如 ViewGroup。通常,如果你覆盖 onDraw(android.graphics.Canvas) 你应该清除这个标志。"

    编辑: 如果你想重新绘制你的视图,你应该调用invalidate()方法

    “使整个视图无效。如果视图可见,onDraw(android.graphics.Canvas) 将在以后的某个时间点被调用。”

    @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 设置边界时,“right”值应高于“left”,例如: 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));

    【讨论】:

    • 它工作但没有时钟。它只是显示了带有图片的第一层。以前它的工作很奇怪,当左上角有一个箭头时
    • 两个 Drawable 都可见吗?
    • 不,不幸的是(我添加了无效,但它们没有出现。可能尺寸错误,现在我将尝试设置一些随机数,如 150 和 150
    • 也没有工作。这仅意味着代码中的某些内容完全错误或缺失。但还是找不到...
    • 再次否定(可能对 arrts.xml 和 styleable 有一些干扰,但我认为没有它就行不通
    猜你喜欢
    • 2013-12-12
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多