2

このコードを使用してNavBarの背景を設定しています。これは、Retinaディスプレイと非Retinaディスプレイでうまく機能します。@2xと通常の画像があります。だから、すべて良い:

UINavigationBar.Appearance.SetBackgroundImage(
     GetImage(ImageTheme.menubar), UIBarMetrics.Default);

このChangeHue()変換を画像に適用して色相を調整すると、Retinaディスプレイでは、画像のサイズが2倍になります。非Retinaディスプレイは問題ありません:

    UINavigationBar.Appearance.SetBackgroundImage(
       ChangeHue(GetImage(ImageTheme.menubar)), UIBarMetrics.Default);
    ...

    UIImage ChangeHue(UIImage originalImage){
        var hueAdjust = new CIHueAdjust() {
            Image = CIImage.FromCGImage(originalImage.CGImage),
            Angle = hue * (float)Math.PI / 180f // angles to radians
        };

        var output = hueAdjust.OutputImage;
        var context = CIContext.FromOptions(null);
        var cgimage = context.CreateCGImage(output, output.Extent);
        var i = UIImage.FromImage(cgimage);
        return i;
}

色相が適用された後のNon-RetinaおよびRetinaディスプレイの結果は次のとおりです。

非網膜

網膜

4

4 に答える 4

3

これらの HACK を無視して、ChangeHueメソッドで次の行を編集します。

var i = UIImage.FromImage(cgimage);

代わりにこれを行うには:

float scale = 1f;
if (UIScreen.MainScreen.RespondsToSelector (new MonoTouch.ObjCRuntime.Selector ("scale"))) {
    scale = UIScreen.MainScreen.Scale; // will be 2.0 for Retina 
}
var i = new UIImage(cgimage, scale, UIImageOrientation.Up);

UIImageこれにより、 に適切に表示される正しい「スケール」情報を持つオブジェクトが返されますUINavigationBar

于 2012-08-12T11:22:07.430 に答える
2

私は CoreImage を試したことはありませんが、CoreGraphics の場合は、スケーリングを使用UIGraphics.BeginImageContextWithOptionsして指定する必要があります0(Retina ディスプレイと非 Retina ディスプレイの両方で自動的に行われます)。

だから私が最初に試みることはあなたを置き換えることです:

var context = CIContext.FromOptions(null);

次のブロックを使用します。

UIGraphics.BeginImageContextWithOptions (new SizeF (size, size), false, 0);
using (var c = UIGraphics.GetCurrentContext ()) {
   var context = CIContext.FromContext (c);
   ...
}
UIGraphics.EndImageContext ();

UPDATE : FromContextiOS (OSX 固有) では使用できないため、上記のコードは機能しません。

于 2012-08-04T13:02:44.963 に答える
0

今のところ、提案する「ハック」が 3 つあります。

ハック #1

この行を置き換えて範囲を強制的に画像をトリミングするには:

var cgimage = context.CreateCGImage(output, output.Extent);

これとともに:

var extent = output.Extent;
if (UIScreen.MainScreen.RespondsToSelector (new MonoTouch.ObjCRuntime.Selector("scale"))) {
    if (UIScreen.MainScreen.Scale == 2f) {
        extent = new System.Drawing.RectangleF(extent.X, extent.Y, extent.Width / 2f, extent.Height / 2f);
    }
}
var cgimage = context.CreateCGImage(output, extent);

ただし、調整された画像の Retina 解像度を「失う」場合 (ソースとして @2x 画像を使用しますが、画像の原点が左下から始まるため、フィルターを適用した後に左下の象限のみが表示されます) .

ハック #2

同じように、ChangeHueメソッドから返された画像を拡大縮小して、ナビゲーション バーを超えないようにすることができます。

var hued = ChangeHue (navBarImage);
if (hued.RespondsToSelector(new MonoTouch.ObjCRuntime.Selector("scale")))
    hued = hued.Scale (new System.Drawing.SizeF(320, 47));
UINavigationBar.Appearance.SetBackgroundImage (hued, UIBarMetrics.Default);

残念なことに、Retina 解像度を再び「失う」ことになりますが、少なくとも画像は正しく表示されます (幅 320 にダウンサンプリングされただけです)。

ハック #3

フィルタリングされた画像をディスクに保存し、UIAppearance「ディスク」上の画像ファイルを使用して設定することができます。コードは次のようになります。

bool retina = false;
if (UIScreen.MainScreen.RespondsToSelector (new MonoTouch.ObjCRuntime.Selector ("scale"))) {
    if (UIScreen.MainScreen.Scale == 2f) {
        retina = true;
    }
}
if (retina) {
    NSError err; // unitialized
    UIImage img = ChangeHue (navBarImage);
    img.AsPNG ().Save ("tempNavBar@2x.png", true, out err);
    if (err != null && err.Code != 0) {
        // error handling
    }
    UINavigationBar.Appearance.SetBackgroundImage (UIImage.FromFile ("tempNavBar.png"), UIBarMetrics.Default);
} else {
    UINavigationBar.Appearance.SetBackgroundImage (ChangeHue (navBarImage), UIBarMetrics.Default);
}

この最後のハックの利点は、画像が正しく見えることです (つまり、Retina 解像度が保持されます)。

私はまだ「完璧な」解決策を探していますが、少なくともこれらのアイデアは、あなたの問題を何らかの方法で「修正」します...

于 2012-08-12T10:06:10.040 に答える
0

MonoTouch チームにバグを報告しました。まもなく解決策を投稿します。

于 2012-08-07T20:09:54.967 に答える