画面切替
snapshotViewとの組み合わせでいける。
let currentView = self.view.snapshotView(afterScreenUpdates: true)! self.view.addSubview(currentView) UIView.transition(with: currentView, duration: 0.5, options: [.transitionFlipFromRight], animations: { currentView.frame = CGRect(origin: CGPoint(x:-self.view.frame.width, y:currentView.frame.origin.y), size: currentView.frame.size) } , completion: { _ in currentView.removeFromSuperview() })
幾つかのメモ 2
ImageButtonはボタン背景がついてしまう。
画像つきボタンはImageViewを使えば良い。
文字付きアイコンはShapeを定義してバッググラウンドに指定する。
<?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <solid android:color="@color/hoge"/> <stroke android:width="1dp" android:color="@color/hoge2" /> <corners android:radius="3dp" /> </shape>
のようなものを作って、textViewのandroid:backgroundに指定すれば良い。
スタイル設定
共通のxmlの色や幅等を共通なものを指定したい場合styleを作りそれを指定するようにできる。
画像回転
view.setRotation(-90F);
レイアウト関連
- Drawableフォルダには画材的なxmlを置く。
- dimensフォルダにはデバイスの大きさごとの指定を置く。
- FrameLayoutは何もしないレイアウト
- RelativeLayoutは何々は何々の上にあるとかを指定するレイアウト
- 絶対座標は使わないこと。
- データバインディングはデータ バインディング ライブラリ | Android Developers
バインドの取得とセット
binding = DataBindingUtil.bind(mView); binding.setHoge(mHoge);
Hogeのところはxmlのdataのnameによって自動的に作られる。bindingの型もdataに設定するtypeから作られる。
xmlはレイアウトを以下で包む必要がある。
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <import type="android.view.View"/> <variable name="hoge" type="jp.co.hoge.app.activity.hogeActivity.HogeItem" /> </data>
バインドの指定は
<TextView android:text='@{hoge.name, default=名前 }' />
エミュレータのプロキシ認証
やったこと。
エミュレータの設定でプロキシ設定する
うまくいかなかったのでコマンドライン上でabd, emulatorを使うことにした。
まずパスを通した。
export PATH=/Applications/adt-bundle-mac-x86_64***/sdk/platform-tools:$PATH export PATH=/Applications/adt-bundle-mac-x86_64***/sdk/tools:$PATH
使い方は
emulator -list-avds
で機種一覧がみれる。
プロキシ経由での実行は
emulator -avd devicename -http-proxy http://username:password@proxyhost:port
abdの使い方は以下に詳しい。
qiita.com
googleのブラウザで認証を求められて入れたら検索できるようになった。
しかし、自分のアプリではproxyでエラーになっている。
アプリをいじる
HTTPクライアントにプロキシ認証を仮にできるようにした。
OkHttpClientを使っているのでリクエストを投げる際に以下のように追加した。
Authenticator authenticator = new Authenticator() { @Override public Request authenticate(Route route, Response response) throws IOException { String credentioal = Credentials.basic(username, password); return response.request().newBuilder().header("Proxy-Authorization", credentioal).build(); } }; Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyhost,port) ); OkHttpClient client = new OkHttpClient().newBuilder() .proxy(proxy) .authenticator(authenticator) .proxyAuthenticator(authenticator) .build();
これでプロキシをさしあたり通すことができた。
OKHTTPの使い方は
qiita.com
幾つかのメモ
アダプター
アイテムからアイテム用のビューへの変換、動的に行われる。getView
convertViewはリサイクルされてきたビューのこと。
データバインディング
DataBindingUtil.inflateでbindingを取得して、そいつにデータをセット、
データはレイアウトのほうで受け取れるようにしておく。
gradleで
dataBinding {
enabled = true
}
レイアウトは
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="hoge" type="com.example.Hoge"/> </data> <LinearLayout android:id="@+id/activity_main" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{hoge.text1}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{hoge.text2}"/> </LinearLayout> </layout>
みたいにする。
レイアウトを使う。
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
GSon
JSONからモデルへ一括変換、モデルはアノテーションで何を受け取るか指定する。
Serializable
@SerializedName("hoge") public String hoge;
ビューのタグ
クラスを一時的にもっておける
レイアウトのinclude
レイアウトを入れ子に。しかし共通化か冗長性か。
ハンドラーにランナブルをなげる。
Handler handler = new Handler(getMainLooper()); handler.post(new Runnable() {
AsyncTaskは簡単バージョン
SimpleDateFormat
日時のフォーマット
CoordinatorLayout
iOSのAutoLayoutに近い
画面遷移カスタマイズ2 viewの遷移
ビューの遷移を真似たい場合snapshotViewとtransitionをくみあわせる。
let currentView = self.view.snapshotView(afterScreenUpdates: true)! self.view.addSubview(currentView) setup() UIView.transition(with: currentView, duration: 0.5, options: [.transitionFlipFromRight], animations: { currentView.frame = CGRect(origin: CGPoint(x:-self.view.frame.width, y:currentView.frame.origin.y), size: currentView.frame.size) } , completion: { _ in currentView.removeFromSuperview() })
画面遷移カスタマイズ
class PushAnimator : NSObject, UIViewControllerAnimatedTransitioning { func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 1.0 } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { guard let fromV = transitionContext.view(forKey: .from) else { return } guard let toV = transitionContext.view(forKey: .to) else { return } let container = transitionContext.containerView container.insertSubview(toV, belowSubview: fromV) UIView.animate(withDuration: self.transitionDuration(using: transitionContext), animations: { fromV.alpha = 0.0 }, completion: { finished in fromV.alpha = 1.0 toV.alpha = 1.0 transitionContext.completeTransition(finished) }) } }
とやって、ナビゲーションのデリゲートに
// 画面遷移 func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { let animator = PushAnimator() switch operation { case .pop,.push: return animator case .none: return nil } }
UIViewのレイアウトライフサイクル
- 制約更新 updateConstraintsIfNeeded() → updateConstraints()が呼ばれる。
- フレーム更新 layoutIfNeeded() → layoutSubViews()が呼ばれる。 端末回転によるフレーム変更、UIScrollViewでcontentOffsetの変更時等
- レンダリング setNeedsDisplay() → drawRect()が呼ばれる。
UIViewControllerのレイアウトライフサイクル
- viewWillLayoutSubviews
- viewDidLyoutSubViews
AutoLayoutの制約式
基本は
A = aB + b
の連立方程式を解く。
Alignment Rectangle (外接矩形)
装飾(影、角丸等)を除いたビュー。AutoLayoutはフレームではなくAlignment Rectangleを用いている。
Alignment Rectangleの表示方法
Edit Scheme のRunのArgumentで起動オプションとして設定できる。
制約定義 NSLayoutConstraint
+ (instancetype)constraintWithItem:(id)view1 // 対象A first itemと呼ばれる。 attribute:(NSLayoutAttribute)attr1 // 対象Aに制約を追加する位置 Left,Right,Top,Bottom,Leading等 relatedBy:(NSLayoutRelation)relation // ビュー間の関係 =,>=,<= toItem:(nullable id)view2 // 対象B オプショナル, second itemと呼ばれる。 attribute:(NSLayoutAttribute)attr2 // 対象Bに制約を追加する位置 Left等 multiplier:(CGFloat)multiplier // 乗数 a constant:(CGFloat)c; // 加える定数 b
制約式を書くと
firstItem.attribute = a * secondItem.attribute + b
NSLayoutAttributte
typedef NS_ENUM(NSInteger, NSLayoutAttribute) { NSLayoutAttributeLeft = 1, NSLayoutAttributeRight, NSLayoutAttributeTop, NSLayoutAttributeBottom, NSLayoutAttributeLeading, // 先頭 NSLayoutAttributeTrailing, // 末尾 NSLayoutAttributeWidth, NSLayoutAttributeHeight, NSLayoutAttributeCenterX, NSLayoutAttributeCenterY, NSLayoutAttributeLastBaseline, NSLayoutAttributeBaseline NS_SWIFT_UNAVAILABLE("Use 'lastBaseline' instead") = NSLayoutAttributeLastBaseline, // テキストのベースライン NSLayoutAttributeFirstBaseline NS_ENUM_AVAILABLE_IOS(8_0), // 複数行テキストの最初の行のベースライン NSLayoutAttributeLeftMargin NS_ENUM_AVAILABLE_IOS(8_0), // 左のマージン NSLayoutAttributeRightMargin NS_ENUM_AVAILABLE_IOS(8_0), // 右のマージン NSLayoutAttributeTopMargin NS_ENUM_AVAILABLE_IOS(8_0), // 上のマージン NSLayoutAttributeBottomMargin NS_ENUM_AVAILABLE_IOS(8_0), // 下のマージン NSLayoutAttributeLeadingMargin NS_ENUM_AVAILABLE_IOS(8_0), NSLayoutAttributeTrailingMargin NS_ENUM_AVAILABLE_IOS(8_0), NSLayoutAttributeCenterXWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),// オブジェクトの左と右のマージンの間のx軸に沿った中心。 UIViewオブジェクトの場合、マージンはlayoutMarginsプロパティで定義される。 NSLayoutAttributeCenterYWithinMargins NS_ENUM_AVAILABLE_IOS(8_0), NSLayoutAttributeNotAnAttribute = 0 };
Intrinsic Content Size
UILabel, UIButton, UIImageでコンテンツを圧縮、切り出しせずに表示するミニマムなサイズ。UILabelではテキストの内容によって変わる。
intrinsicContentSizeによって取得可能
Content Hugging Priority 大きくなりにくさ
縦横それぞれに指定可能。コンテンツに沿う優先度。Intrinsic Content Sizeにあわせてサイズが変化する。この優先度が低いと他の制約に従ってIntrinsic Content Sizeよりも大きくなる。
Content Compression Resistance Priority 小さくなりにくさ
前述の圧縮バージョン
Adaptive Layout
商品の値段とNSNumberFormatter
SKProductの価格の加工などで使う。
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; formatter.formatterBehavior = NSNumberFormatterBehavior10_4; formatter.numberStyle = NSNumberFormatterCurrencyStyle; formatter.locale = locale; NSString *string = [formatter stringFromNumber:price];