使用来自其原始类的自定义 android AnalogClock 设置时间

Set time with custom android AnalogClock from its original class(使用来自其原始类的自定义 android AnalogClock 设置时间)

本文介绍了使用来自其原始类的自定义 android AnalogClock 设置时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 Internet 上提供的 Android 开源项目的 AnalogClock 源代码制作自定义 AnalogClock 类.

I want to make a custom AnalogClock class using source code of AnalogClock by Android Open Source Project that is available in the internet.

我想让时钟设置我想要的时间,而不是当前时间.我没有找到一个明确的例子来说明如何做到这一点,所以也许这篇文章会有用.将源代码复制到新文件后,出现一些错误.下面是AnalogClock的原始源码:

I want to make the clock set the time that I want, not the current time. I didn't find a clear example on how to do it so maybe this post will be useful. After copying source code to new file, I get some errors. Below is the original source code of AnalogClock:

/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.widget;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.text.format.Time;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RemoteViews.RemoteView;

import java.util.TimeZone;

/**
 * This widget display an analogic clock with two hands for hours and
 * minutes.
 */
@RemoteView
public class AnalogClock extends View {
    private Time mCalendar;

    private Drawable mHourHand;
    private Drawable mMinuteHand;
    private Drawable mDial;

    private int mDialWidth;
    private int mDialHeight;

    private boolean mAttached;

    private final Handler mHandler = new Handler();
    private float mMinutes;
    private float mHour;
    private boolean mChanged;

    public AnalogClock(Context context) {
        this(context, null);
    }

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

!!Error mContext -> 将 mContext 更改为上下文(我可以这样做)吗?

    public AnalogClock(Context context, AttributeSet attrs,
                       int defStyle) {
        super(context, attrs, defStyle);
        Resources r = mContext.getResources();

!!无法解决错误 com.android.internal.R.我找到了解决这个问题的方法

!!Error com.android.internal.R cannot be resolved. I found a solution to this problem with

mDial = r.getDrawable(Resources.getSystem().getIdentifier("clock_dial","drawable", "android"));

其他行也一样,只是更改名称和可绘制或可样式化.

And same for other lines just changing name and either drawable or styleable.

vvvv----但是下面的代码我还是有问题.

        TypedArray a =
                context.obtainStyledAttributes(
                        attrs, com.android.internal.R.styleable.AnalogClock, defStyle, 0);

^^^^----我不知道如何更改它并使其工作

        mDial = a.getDrawable(com.android.internal.R.styleable.AnalogClock_dial);
        if (mDial == null) {
            mDial = r.getDrawable(com.android.internal.R.drawable.clock_dial);
        }

        mHourHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_hour);
        if (mHourHand == null) {
            mHourHand = r.getDrawable(com.android.internal.R.drawable.clock_hand_hour);
        }

        mMinuteHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_minute);
        if (mMinuteHand == null) {
            mMinuteHand = r.getDrawable(com.android.internal.R.drawable.clock_hand_minute);
        }

        mCalendar = new Time();

        mDialWidth = mDial.getIntrinsicWidth();
        mDialHeight = mDial.getIntrinsicHeight();
    }

    @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);
        }

        // NOTE: It's safe to do these after registering the receiver since the receiver always runs
        // in the main thread, therefore the receiver can't run before this method returns.

        // The time zone may have changed while the receiver wasn't registered, so update the Time
        mCalendar = new Time();

        // Make sure we update to the current time
        onTimeChanged();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mAttached) {
            getContext().unregisterReceiver(mIntentReceiver);
            mAttached = false;
        }
    }

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

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

        float hScale = 1.0f;
        float vScale = 1.0f;

        if (widthMode != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) {
            hScale = (float) widthSize / (float) mDialWidth;
        }

        if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) {
            vScale = (float )heightSize / (float) mDialHeight;
        }

        float scale = Math.min(hScale, vScale);

        setMeasuredDimension(resolveSize((int) (mDialWidth * scale), widthMeasureSpec),
                resolveSize((int) (mDialHeight * scale), heightMeasureSpec));
    }

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

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

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

!!!错误 - mRight、mLeft、mBotton、mTop 来自哪里?该文件中没有声明

        int availableWidth = mRight - mLeft;
        int availableHeight = mBottom - mTop;

        int x = availableWidth / 2;
        int y = availableHeight / 2;

        final Drawable dial = mDial;
        int w = dial.getIntrinsicWidth();
        int h = dial.getIntrinsicHeight();

        boolean scaled = false;

        if (availableWidth < w || availableHeight < h) {
            scaled = true;
            float scale = Math.min((float) availableWidth / (float) w,
                                   (float) availableHeight / (float) h);
            canvas.save();
            canvas.scale(scale, scale, x, y);
        }

        if (changed) {
            dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
        }
        dial.draw(canvas);

        canvas.save();
        canvas.rotate(mHour / 12.0f * 360.0f, x, y);
        final Drawable hourHand = mHourHand;
        if (changed) {
            w = hourHand.getIntrinsicWidth();
            h = hourHand.getIntrinsicHeight();
            hourHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
        }
        hourHand.draw(canvas);
        canvas.restore();

        canvas.save();
        canvas.rotate(mMinutes / 60.0f * 360.0f, x, y);

        final Drawable minuteHand = mMinuteHand;
        if (changed) {
            w = minuteHand.getIntrinsicWidth();
            h = minuteHand.getIntrinsicHeight();
            minuteHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
        }
        minuteHand.draw(canvas);
        canvas.restore();

        if (scaled) {
            canvas.restore();
        }
    }

    private void onTimeChanged() {
        mCalendar.setToNow();

        int hour = mCalendar.hour;
        int minute = mCalendar.minute;
        int second = mCalendar.second;

        mMinutes = minute + second / 60.0f;
        mHour = hour + mMinutes / 60.0f;
        mChanged = true;
    }

    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
                String tz = intent.getStringExtra("time-zone");
                mCalendar = new Time(TimeZone.getTimeZone(tz).getID());
            }

            onTimeChanged();

            invalidate();
        }
    };
}

谁能告诉我:

  1. 如何让这个类像普通的 AnalogClock 一样工作
  2. 如何在这个类中编写一个方法来应用我将提供给它的时间?

推荐答案

使用 setTime() 方法自定义 MyAnalogClock.

花了一些时间后,我终于设法解决了这个问题.我希望它对某人有用.只需调用 setTime(hours, minutes, seconds) 方法即可设置时间.

After spending some time I finally managed to solve the problem. I hope it will be useful for someone. You can set time simply by calling setTime(hours, minutes, seconds) method.

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.text.format.Time;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RemoteViews.RemoteView;

/**
 * This widget display an analogic clock with two hands for hours and
 * minutes.
 */
@RemoteView
public class MyAnalogClock extends View {

    private Drawable mHourHand;
    private Drawable mMinuteHand;
    private Drawable mSecondHand;
    private Drawable mDial;

    private int mDialWidth;
    private int mDialHeight;

    private float mSeconds;
    private float mMinutes;
    private float mHour;

    Context mContext;

    public MyAnalogClock(Context context) {
        super(context);
    }

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

    public MyAnalogClock(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;
       // mDial = a.getDrawable(com.android.internal.R.styleable.AnalogClock_dial);
       // if (mDial == null) {
            mDial = r.getDrawable(R.drawable.clock_dial);
       // }

      //  mHourHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_hour);
      //  if (mHourHand == null) {
            mHourHand = r.getDrawable(R.drawable.clock_hour);
      //  }

     //   mMinuteHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_minute);
     //   if (mMinuteHand == null) {
            mMinuteHand = r.getDrawable(R.drawable.clock_minute);
            mSecondHand = r.getDrawable(R.drawable.clockgoog_minute);
     //   }

        mDialWidth = mDial.getIntrinsicWidth();
        mDialHeight = mDial.getIntrinsicHeight();
    }

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

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

        float hScale = 1.0f;
        float vScale = 1.0f;

        if (widthMode != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) {
            hScale = (float) widthSize / (float) mDialWidth;
        }

        if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) {
            vScale = (float )heightSize / (float) mDialHeight;
        }

        float scale = Math.min(hScale, vScale);

        setMeasuredDimension(resolveSize((int) (mDialWidth * scale), widthMeasureSpec),
                resolveSize((int) (mDialHeight * scale), heightMeasureSpec));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //Here you can set the size of your clock
        int availableWidth = 70;
        int availableHeight = 70;

        //Actual size
        int x = availableWidth / 2;
        int y = availableHeight / 2;

        final Drawable dial = mDial;
        int w = dial.getIntrinsicWidth();
        int h = dial.getIntrinsicHeight();

        boolean scaled = false;

        if (availableWidth < w || availableHeight < h) {
            scaled = true;
            float scale = Math.min((float) availableWidth / (float) w,
                                   (float) availableHeight / (float) h);
            canvas.save();
            canvas.scale(scale, scale, x, y);
        }

        dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
        dial.draw(canvas);

        canvas.save();
        canvas.rotate(mHour / 12.0f * 360.0f, x, y);
        w = mHourHand.getIntrinsicWidth();
        h = mHourHand.getIntrinsicHeight();
        mHourHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
        mHourHand.draw(canvas);
        canvas.restore();

        canvas.save();
        canvas.rotate(mMinutes / 60.0f * 360.0f, x, y);
        w = mMinuteHand.getIntrinsicWidth();
        h = mMinuteHand.getIntrinsicHeight();
        mMinuteHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
        mMinuteHand.draw(canvas);
        canvas.restore();

        canvas.save();
        canvas.rotate(mSeconds, x, y);
        w = mSecondHand.getIntrinsicWidth();
        h = mSecondHand.getIntrinsicHeight();
        mSecondHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
        mSecondHand.draw(canvas);
        canvas.restore();
        if (scaled) {
            canvas.restore();
        }
    }

    public void setTime(int hours, int minutes, int seconds)
    {
        mSeconds = 6.0f*seconds;
        mMinutes = minutes + seconds / 60.0f;
        mHour = hours + mMinutes / 60.0f;
    }
}

您还应该在 drawable 文件夹中放置 4 个可绘制文件,并使用以下代码在 values 文件夹中创建(或更新)attrs 文件:

You should also put 4 drawable files in the drawable folder and create (or update) the attrs file in values folder with the following code:

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

这篇关于使用来自其原始类的自定义 android AnalogClock 设置时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:使用来自其原始类的自定义 android AnalogClock 设置时间

基础教程推荐