簡體   English   中英

Android顯示尺寸和可繪制尺寸縮放

[英]Android display Dimensions and Drawable size scaling

這是下一個階段: 在自定義android AnalogClock手中縮放和對齊 ...這個。

不久,我意識到Drawable無法縮放,如果它適合大小框,則將顯示它。 否則不行。 所以現在我需要一個位圖來縮放它,然后轉換回Drawable並繪制它。 它看起來並不優雅,但是根據我發現的信息,我看不到其他任何方式。

(想法是創建帶有一些特殊技巧的警報應用程序。首先,我需要時鍾指針。為了創建自定義時鍾,我使用了自己的類,該類擴展了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.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
import android.widget.ImageView;



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

private Drawable mHourHand;
private Drawable mMinuteHand;

private int sizeXHour;
private int sizeXMinute;
private int sizeYHour;
private int sizeYMinute;
private int xHour;
private int xMinute;
private int yHour;
private int yMinute;
private int w;
private int h;

private Drawable Hh;
private Bitmap HourHnd;
private Drawable Mh;
private Bitmap MinuteHnd;

private boolean mAttached;

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

Context mContext;

// Getters&setters

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


//Ctors

@SuppressWarnings("deprecation")
public Clock(Context context) {
super(context);
Resources r = context.getResources();
mContext=context;

Hh = r.getDrawable(R.drawable.hours);
HourHnd = ((BitmapDrawable)Hh).getBitmap();

Mh = r.getDrawable(R.drawable.minuts);
MinuteHnd = ((BitmapDrawable)Mh).getBitmap();   

// Here I try to take screen dimensions    

WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR2)
{

    DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();

    h = metrics.heightPixels;
    w = metrics.widthPixels;

}
else
{
    Display d = wm.getDefaultDisplay();
    h = d.getWidth();
    w = d.getHeight();
}


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

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

    mHourHand = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(HourHnd, sizeXHour, sizeYHour, true));   // Here it says that sizeXHour etc. is 0;

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

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

mMinuteHand = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(MinuteHnd, sizeXMinute, sizeYMinute, true));


setWillNotDraw(false);
}



@SuppressWarnings("deprecation")
public Clock(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
    //setWillNotDraw(false);
    Resources r = context.getResources();
     mContext=context;


     Hh = r.getDrawable(R.drawable.hours);
     HourHnd = ((BitmapDrawable)Hh).getBitmap();

     Mh = r.getDrawable(R.drawable.minuts);
     MinuteHnd = ((BitmapDrawable)Mh).getBitmap();   


     WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);

     //if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR2)
     //{

        //DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();

        //h = metrics.heightPixels;
        //w = metrics.widthPixels;

     //}
     //else
     //{
         Display d = wm.getDefaultDisplay();
         h = d.getWidth();
         w = d.getHeight();
     //}


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

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

        mHourHand = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(HourHnd, sizeXHour, sizeYHour, true));

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

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

        mMinuteHand = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(MinuteHnd, sizeXMinute, sizeYMinute, true));


     setWillNotDraw(false);

}


@SuppressWarnings("deprecation")
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);
         Hh = r.getDrawable(R.drawable.hours);
         HourHnd = ((BitmapDrawable)Hh).getBitmap();


         //mMinuteHand = r.getDrawable(R.drawable.minuts);
         Mh = r.getDrawable(R.drawable.minuts);
         MinuteHnd = ((BitmapDrawable)Mh).getBitmap();   



         WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         //if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR2)
         //{

         // DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();

            //h = metrics.heightPixels;
         // w = metrics.widthPixels;
             //h = size.x;
             //w = size.y;
         //}
         //else
        // {
             Display d = wm.getDefaultDisplay();
             h = d.getWidth();
             w = d.getHeight();
         //}


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

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

            mHourHand = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(HourHnd, sizeXHour, sizeYHour, true));

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

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

            mMinuteHand = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(MinuteHnd, sizeXMinute, sizeYMinute, true));


         setWillNotDraw(false);
}



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

    }

}



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

    int width = widthSize; 
    int height = heightSize;


    setMeasuredDimension(width, height);


}


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




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

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


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



        canvas.rotate(mMinutes / 60.0f * 360.0f, xMinute, yMinute);

        if (changed) {
        mMinuteHand.setBounds((w / 2 - xMinute), (h / 2 - yMinute), sizeXMinute, sizeYMinute);
        /
        }
        mMinuteHand.draw(canvas);
        //canvas.restore();
        canvas.save();


}
        }

很抱歉再次輸入較大的代碼。 現在,Eclipse中的圖形布局管理器指出此錯誤:

java.lang.IllegalArgumentException: width and height must be > 0
at android.graphics.Bitmap.createBitmap(Bitmap.java:808)
at android.graphics.Bitmap.createBitmap(Bitmap.java:787)
at android.graphics.Bitmap.createBitmap(Bitmap.java:719)
at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:595)
at ee.st.running.dreamyclock.Clock.<init>(Clock.java:268)
at ee.st.running.dreamyclock.Clock.<init>(Clock.java:161)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(    at       sun.reflect.NativeConstructorAccessorImpl.newInstance(    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(    at java.lang.reflect.Constructor.newInstance(    at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.instantiateClass(ProjectCallback.java:438)
at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.loadView(ProjectCallback.java:190)
at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:207)
at android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:132)
at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:802)
at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:64)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:778)
at android.view.LayoutInflater.inflate(LayoutInflater.java:500)
at android.view.LayoutInflater.inflate(LayoutInflater.java:381) 

結果,sizeXHour等為0; 我不確定根本不會畫出鍾針,但是我仍然需要獲取屏幕尺寸。 有什么想法嗎?

PS異常首先在這里:mHourHand = new BitmapDrawable(getResources(),Bitmap.createScaledBitmap(HourHnd,sizeXHour,sizeYHour,true));

因此出現此異常是因為eclipse無法完全解析某些屬性,例如樣式等。發生錯誤時在可視化編輯器中對此進行了解釋。 一些解決方法是使用View.isInEditMode()

至於獲取屏幕的大小,您使用的代碼(帶有Display )是正確的,應該可以正常工作。 如果時鍾不出現,則表示出現了其他錯誤,而不是測量結果。

我認為測量屏幕的大小通常不是一個好主意,因為您假設您的視圖與整個屏幕匹配。 但是沒有什么可以阻止您將視圖放置在其他容器中,因此視圖的實際尺寸要小一些。

然后,我建議您使用View.getWith()View.getHeight()來限制視圖范圍。 注意:由於視圖是在構造視圖之后進行測量的,因此在構造函數中使用這些方法將返回0。您必須等到視圖布局完畢后才能檢索其尺寸:用於此View.getViewTreeObserver().setOnGlobalLayoutListener


另外:

  • 布局好視圖后,將自動調用onDraw ,因此無需在onMeasure的末尾調用invalidate

  • 布爾值更改沒有效果(似乎)。 如果要使用它僅允許在更改大小的情況下繪制時鍾,則這是一個壞主意:這將導致視圖無效時視圖被“擦除”,直到其邊界改變為止。


這是我的工作方式:

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

    private Drawable mHourHand;
    private Drawable mMinuteHand;

    private Drawable Hh;
    private Drawable Mh;

    private boolean mAttached;

    static private float mMinutes = 43;
    static private float mHour = 5;

    Context mContext;

    // Getters&setters

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

    // Ctors

    {
        initView();
    }

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

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

    public Clock(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    private void initView() {
        Resources r = getContext().getResources();
        mContext            = getContext();
        Hh                  = r.getDrawable(R.drawable.hours);
        Mh                  = 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);

        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int w               = r - l;
        int h               = b - t;

        mHourHand           = Hh;
        mMinuteHand         = Mh;

        // They will always be drawn centered inside the view
        mHourHand.setBounds(
                (w - mHourHand.getIntrinsicWidth()) / 2,
                (h - mHourHand.getIntrinsicHeight()) / 2,
                (w + mHourHand.getIntrinsicWidth()) / 2,
                (h + mHourHand.getIntrinsicHeight()) / 2
        );
        mMinuteHand.setBounds(
                (w - mMinuteHand.getIntrinsicWidth()) / 2,
                (h - mMinuteHand.getIntrinsicHeight()) / 2,
                (w + mMinuteHand.getIntrinsicWidth()) / 2,
                (h + mMinuteHand.getIntrinsicHeight()) / 2
        );
    }

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

        // Rotate the center of the view (here the canvas is clipped and translated so that its clipped bounds are these of this view).
        canvas.save();
        canvas.rotate(mHour * 360/12, getWidth()/2, getHeight()/2);
        mHourHand.draw(canvas);
        canvas.restore();

        canvas.save();
        canvas.rotate(mMinutes * 360/12, getWidth()/2, getHeight()/2);
        mMinuteHand.draw(canvas);
        canvas.restore();
    }
}

然后,這是一個在ActivityInstrumentationTestCase2內部運行的測試:

public void test() throws InterruptedException {
    getActivity().runOnUiThread(new Runnable() {

        @Override
        public void run() {
            getActivity().setContentView(R.layout.clock_layout);
        }
    });
    Thread.sleep(3000);
}

和布局文件:

<?xml version="1.0" encoding="utf-8"?>
<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"
    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" />
    <!-- A modified layout params to match_parent, wrap_content results in the view having size (0,0) -->
    <com.example.clock.Clock
         android:id="@+id/clock"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_alignTop="@+id/view1"
         android:layout_centerHorizontal="true" />
</RelativeLayout>

我不了解您的所有縮放代碼,因此我擺脫了它,並使其盡可能簡單,然后可以從中進行操作,並在需要時添加一些調整大小的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM