フリープログラマー日記

iOS,アンドロイド開発を気ままにしながら生きてるおじさんのブログです。

第5回 iOS と Android で画像を表示するプログラム

色々なTipsをご紹介するのが、このブログの最大の目標ですが、
やみくもにコードを並べても芸がないので、方向性を出してみます。

3年くらい前に作ったiOSアプリをご覧ください。

f:id:momonga117:20180505222544p:plain

複数個のストップウォッチの機能を持たせたアプリです。
左側はメニュー画面。ラップ数や時間を設定できます。
真ん中は計測中の画面。選手が通過すると名前のついたボタンを押します。
右側は、記録確認画面。周回タイムが人数分表示されます。

用途としては、陸上競技長距離走のトレーニング用として活用してもらっています。

この時は、あまり何も知らずにピッカービューなるものを使い、Androidへの移植をしないまま、終わっています。

ソースはスパゲッティ状態で無残な状態で・・・トホホ・・

このアプリをリメイクしながら、私の拙いテクニックを公開しようと考えています。
画像貼り付け、ボタン作成、タイマー、設定の記録・・・
色々な題材を見つけていけそうです。

まず最初に画像ファイルの貼り付けです。

画像ファイルが出てきました。

f:id:momonga117:20180505232030p:plain

うむむ、恥ずかしいことに綴りが違うじゃありませんか。
これもリメイクしなくちゃね。

さて、
では、左の画像を画面の中央に貼ってみます。
この画像は、幅が300、高さが,250のPNGファイルで作っていました。
これを使って、貼り付けるプログラムを作って行きます。

まず、iOS(swift)版

app delegate.swift以外はこの2つのファイルです。

//
//  MainMenu.swift
//  BrogX
//
//  Created by  xxxxxxxxxxxxx on 2018/05/06.
//  Copyright © 2018年 xxxxxxxxxxxxx. All rights reserved.
//
import UIKit

class MainMenu: UIView {
    

    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    override func draw(_ rect: CGRect) {

        super.draw(rect)
        
        // このビューのサイズ
        let viewWidth:CGFloat = self.bounds.width
        let viewHeight:CGFloat = self.bounds.height
        
        // Bitmap画像を用意
        let menuBitmap = UIImage(named: "track.png")
        
        // 画像のサイズを取得する
        let srcWidth:CGFloat = menuBitmap!.size.width
        let srcHeight:CGFloat = menuBitmap!.size.height
        
        
        // 表示サイズを決定する
        let dstWidth:CGFloat = viewWidth*9/10
        let dstHeight:CGFloat = dstWidth * srcHeight / srcWidth
   
        // 中央に表示するための座標
        let left:CGFloat = viewWidth/2 - dstWidth/2
        let top:CGFloat = viewHeight/2 - dstHeight/2
        
        // ビットマップの表示  (注意) 第3、4項は width,height
        menuBitmap!.draw(in: CGRect(x: left, y: top, width: dstWidth, height: dstHeight))
        
    }
    
}
//  Entrance.swift
//  BrogX
//
//  Created by  xxxxxxxxxxxxx on 2018/05/06.
//  Copyright © 2018年 xxxxxxxxxxxxx. All rights reserved.
//

import UIKit

class Entrance: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func viewDidAppear(_ animated: Bool) {
        
        // 端末のサイズを取得
        // UIScreennクラスが端末サイズを持っている
        let width: CGFloat = UIScreen.main.bounds.size.width
        let height: CGFloat = UIScreen.main.bounds.size.height
        
        // MainMenu のインスタンスを作成。
        let mainMenu:MainMenu = MainMenu(frame: CGRect.zero)
        
        // ビューの位置がわかるように背景に色付け(黄色)
        mainMenu.backgroundColor = UIColor.yellow  // 背景色は黄色
        

        // ビューのサイズを設定
        mainMenu.frame = CGRect(x: 0, y: 0, width: width, height: width)
        
        mainMenu.center = CGPoint(x: width/2, y: height/2)
        self.view.addSubview(mainMenu)
        
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

続いて、 Android(java)版。

こちらは、MainActivity.java以外の2つ
MainMenu.java と Entrance.java になります。

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;

public class MainMenu extends View {

    // コンストラクタ
    public MainMenu(Context context) {

        super(context);

    }

    @Override
    protected void onDraw(Canvas canvas) {

        final int width = getWidth();
        final int height = getHeight();

        super.onDraw(canvas);
        final Paint paint = new Paint();

        // Bitmap画像を用意
        final Bitmap menuBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.track);

        // 画像のサイズを取得する
        final int srcWidth = menuBitmap.getWidth();
        final int srcHeight = menuBitmap.getHeight();
        final Rect srcRect = new Rect(0,0,srcWidth,srcHeight);

        // 表示サイズを決定する
        final int dstWidth = width*9/10;
        final int dstHeight = dstWidth * srcHeight / srcWidth;
        final Rect dstRect = new Rect(width/2-dstWidth/2,height/2-dstHeight/2,width/2+dstWidth/2,height/2+dstHeight/2);

        // 画像を表示する。
        canvas.drawBitmap(menuBitmap,srcRect,dstRect,paint);

    }
}
import android.content.Context;
import android.graphics.Color;
import android.widget.RelativeLayout;

public class Entrance extends RelativeLayout {

    public Entrance(Context context) {

        super(context);

    }

    public void enterMenu() {

        // 端末のサイズを取得
        final int width = this.getWidth();
        final int height = this.getMeasuredHeight();

        // MainMenu のインスタンスを作成。
        MainMenu mainMenu = new MainMenu(getContext());

        // ビューの位置がわかるように背景に色付け(黄色)
        mainMenu.setBackgroundColor(Color.YELLOW);

        // Androidではレイアウトパラメーターを使用
        LayoutParams mainMenuParams = new LayoutParams(
                width,width
        );
        mainMenuParams.addRule(CENTER_IN_PARENT);
        mainMenuParams.addRule(CENTER_IN_PARENT);
        // ビューを画面中央に表示
        addView(mainMenu, mainMenuParams);

    }
}


実行するとこちら。
f:id:momonga117:20180506201913p:plain

黄色はUIView & View が見えるようにしています。
最終的に白になりますが。

ここで、ImageViewを使わない理由を言わないとね。

まず、画像の扱いを細かく制御するのはこの方が楽だからです。
拡大とか縮小とか、おまかせでやっても思う通りにならなかったりするので。

あと、メインメニューのクラスにボタンの働きなども詰め込んでいってメニューを扱うカスタムビューにしたいからです。

もう一つ、異機種間で同じ設計のプログラムを書くには最初から、両対応のプログラムにすることが必要だと考えています。

まあ、違う考えもあるとは思いますが「我が道を行く」です。



前にも書いてますが、私の独断と偏見に満ちたブログですので、参考にされる方はご自由にしていただいて構いません。

まとまったものがなかなかできない方には参考になるのではと思います。(偉そうに言ってすみません)

これからも頑張りますので、よろしくお願いします。