Ruby on RailsとTwitter Bootstrap 3でパンくずリストを追加する方法

breadcrumbs

breadcrumbs_on_railsがオススメ

breadcrumbs_on_rails はbootstrapに限らずパンくずリスト(Breadcrumbs)の実装が簡単に出来るのでオススメです。

インストール方法

Gemfileに下記を追記:

gem "breadcrumbs_on_rails"

$ bundle installでサクっとインストールしましょう。

基本の使い方

controllerに記述する

class MyController

  add_breadcrumb "home", :root_path
  add_breadcrumb "my", :my_path

  def index
    # ...

    add_breadcrumb "index", index_path
  end

end

app/controllers/application_controller.rbに追加する事で、サイト全体でデフォルトのパンくずアイテムを追加出来ます。
「ホーム」みたいな項目はそっちに記述するといいかと思います。

viewに記述する

slimだと以下のような感じでOK:

- title "タイトル"
- add_breadcrumb title, request.fullpath

controllerで指定したものの後に追加されます。
viewに書く方がMVCアーキテクチャにより適合していますね。

出力する

app/views/layouts/application.html.slimなどの任意の行に下記を追記しましょう。

= render_breadcrumbs

Bootstrap 3で使う

上記の手順でパンくずリストを出力すると、下記のように単純にaタグの羅列になります。

<a href="http://odoruinu.net/">Home</a> > <a href="/blog">Blog</a> > <a href="/blog/page">Page</a>

ここでは、bootstrap 3のスタイルで書きたいので下記のように出力して欲しいところ:

<ol class="breadcrumb">
  <li><a href="http://odoruinu.net/">Home</a></li>
  <li><a href="/blog">Blog</a></li>
  <li class="active">Page</li>
</ol>

Bootstrap用ビルダーを作る

breadcrumbs_on_railsではカスタムなフォーマットでパンくずリストを出力するための方法が用意されています。
これを Builder と呼びます。

さっそくBootstrap用のBuilderを作ってみましょう。
以下のような内容をlib/bootstrap_breadcrumbs_builder.rbに作ります:

class BootstrapBreadcrumbsBuilder < BreadcrumbsOnRails::Breadcrumbs::Builder
  def render
    @context.render "/application/breadcrumbs", elements: @elements, b: self
  end

  def compute_name(element)
    case name = element.name
    when Symbol
      @context.send(name)
    when Proc
      name.call(@context)
    else
      name.to_s
    end
  end

  def compute_path(element)
    case path = element.path
    when Symbol
      @context.send(path)
    when Proc
      path.call(@context)
    else
      @context.url_for(path)
    end
  end
end

そして、app/views/application/_breadcrumbs.html.slimに以下のようなファイルを作ります。

- unless elements.length==1 && current_page?( b.compute_path(elements[0]) )
  ol.breadcrumb
    - elements.each do |element|
      li class=( "active" if current_page?( b.compute_path(element) ) )
        =link_to_unless_current b.compute_name(element), b.compute_path(element), element.options

最後に、レイアウトのファイルに以下のように追記すればOK!

#!slim
= render_breadcrumbs builder: ::BootstrapBreadcrumbsBuilder

Breadcrumbs

バッチリ!

Twitter Bootstrapで良いアイコンが無い?じゃあFontAwesome使おう!

FontAwesome

Twitter Bootstrapのglyphicon便利ですよね!手軽に色んなアイコンが使えて。
でもなんか足りない!こう、もっとこういうのが欲しい!!って時にオススメなのがFontAwesomeです。

FontAwesome-icons

紹介しきれないぐらいに沢山のアイコンが揃っています!!
twitterやfacebookなどの有名サービスのアイコンも用意されているので、これさえあれば滅多に困らないと思います。

[iOS] 動的なレイアウトを超手軽に実装する方法

autolayout

概要

AutoLayoutが超手軽に使える、Masonryをご紹介します!

AutoLayoutで動的レイアウト、しかし…

不特定なサイズの画像や長さのテキストを取り扱う時、どうしても固定サイズのViewレイアウトでは限界があります。
コンテンツのサイズに合わせて、動的にレイアウトを調整する必要があります。
また、単にText ViewやImage Viewのサイズを変えればいいのではなく、周辺のViewも調整が必要なので結構大変です。

そんな動的レイアウトの要件に対しては、AutoLayoutがよく使用されます。
AutoLayoutは、親Viewのサイズ変更があった時に子View同士の間隔やサイズを自動で調節してくれる技術です。
そのレイアウト方法は、Constraint(制約)と呼ばれるものをViewに与える事で定義します。
AutoLayoutを使うと有効な時とその利点は以下の2つです:

  1. Interface Builderを使って、動的なサイズや配置のViewヒエラルキーを組む時
    • 親Viewのサイズ変更に合わせてレイアウトしなおす処理を追加で書く必要が無くなる
    • 例: 不特定サイズの画像を表示するTable view cell内のViewのレイアウト
  2. Interface Builderを使わないでViewを組む時
    • 位置とサイズベースではなく、制約ベースでレイアウトを定義できる
    • 例: 「親Viewに対して上下左右に10pxのマージンを設けた子Viewを配置」というセマンティクスで定義できる

2つめは、異なるスタイルで記述できるという事なんですが、利点となるには苦しい理由があります。
僕の場合はInterface Builderを使わないので、2番が利点にならなければ使う意味はほぼありません。

超めんどくさいAutoLayoutの記述

コードベースでのUI実装において、AutoLayoutが利点となるには苦しいその理由は、AutoLayoutをコードで記述すると超冗長になるという点です。
つまり、全然簡単じゃない!楽じゃない!

「親Viewに対して上下左右に10pxのマージンを設けた子Viewを配置」を実際にコードで記述した場合、以下のようになります。

#!objectivec
UIView *superview = self;

UIView *view1 = [[UIView alloc] init];
view1.translatesAutoresizingMaskIntoConstraints = NO;
view1.backgroundColor = [UIColor greenColor];
[superview addSubview:view1];

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[superview addConstraints:@[

    //view1 constraints
    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeTop
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeTop
                                multiplier:1.0
                                  constant:padding.top],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeLeft
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeLeft
                                multiplier:1.0
                                  constant:padding.left],   

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeBottom
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeBottom
                                multiplier:1.0
                                  constant:-padding.bottom],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeRight
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeRight
                                multiplier:1
                                  constant:-padding.right],

 ]];

はい、やってられないですね!

Masonryでお手軽AutoLayout

AutoLayoutは便利だけど、NSLayoutConstraintによる記述は前述の通り冗長で面倒です。
それが原因で、利点を感じられず個人的に今まで全く使ってきませんでした。

しかし、Masonryというライブラリがこの悩みを一気に解決してくれました。
このライブラリは、AutoLayoutの学習コストを最小限に押さえつつ、少ない記述量で使用できるようにしてくれるものです。
これは嬉しい!

前述の例「親Viewに対して上下左右に10pxのマージンを設けた子Viewを配置」をMasonryで記述すると:

#!objectivec
UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(superview).with.insets(padding);
}];

とっっっっっても簡単ですね!!
制約ベースでの記述は、HTMLとCSSのような感覚で書けるので、とても重宝しそうです。

[iOS] チップスの吹き出しを簡単に表示する方法

酔っぱらってるけど更新します!!

アプリに新しいボタンを追加した時とか、初めて利用する人に向けてUIの説明をしたい時ってありますよね。
それも、出来るだけユーザさんの操作の邪魔をせずに。
そういう時に、ボタンの上下左右いずれかの場所にバルーンを表示できたら便利ですよね!
そんなバルーンを手軽に表示できるのが、CMPopTipViewです!動作させると以下のようにいい感じで表示してくれます:

CMPopTipView

CMPopTipView

もちろん、バルーンの見た目のカスタマイズ性も充分にあります。
枠や陰、ボコっと出っ張ったグラデーションなどを調整できます。
使い方も簡単!
以下のようなコードを書くだけ!

// PopTipViewのインスタンス作成
CMPopTipView *navBarLeftButtonPopTipView = [[CMPopTipView alloc] initWithMessage:@"A Message"];
navBarLeftButtonPopTipView.delegate = self;
// ナビゲーションバーのボタンに位置を合わせるように指定して表示
[navBarLeftButtonPopTipView presentPointingAtBarButtonItem:self.navigationItem.leftBarButtonItem animated:YES];

// PopTipViewが非表示になった時に呼ばれるデリゲートメソッド
- (void)popTipViewWasDismissedByUser:(CMPopTipView *)popTipView {
  // クリーンアップコード
}

お試しあれ!

[iOS7] かっこいいカスタムAlertViewモジュール3選

iOS7向けの多機能なアラート、かっこいいデザインのアラートなどを紹介します!

多機能アラート: LMAlertView

GitHub repository

標準アラートビューと同じ見た目で、アラートの中に地図を埋め込んだりアプリ評価を出したりできます。これはイカス!!いい感じのコメントフォームとか簡単に実装できますね!

プログレス表示に便利: MBProgressHUD

GitHub repository

アラートとは少し違うけど似たようなもんなのでご紹介w 処理の進捗表示といった一時的に表示する用途に向いています。
デザインがかっこいい!!使い方も簡単!!バリエーション豊富!!
個人的にはキャンセルボタンが欲しいかな。




デザイン重視: MLAlertView

GitHub repository

こちらはタイトルバーに色がついててちょっとオシャレなアラート。動きもポップ!


[iOS] 矩形領域にスポットライトをあててUIを手軽に説明できるWSCoachMarksView

注目してほしい箇所以外を暗くして、説明文を表示できるコンポーネント。
初回起動時にざっとアプリのUIの使い方を説明するのに調度いいですね!!

ビデオがうまく表示されない方はこちら

WSCoachMarksView on GitHub

iOS7でtweetbotっぽいぼかしアニメーションつきModalView

概要

tweetbot 3では、モーダルビューの表示方法が下記画像のように凝っている。
ツイートの長押しでアクションメニューが表示される際に、直前の画面が後ろに下がりぼかしがかかる。
メニューは、それにオーバーレイされて表示される。
これ、チョーかっこいいので真似してみた。

こちらが、真似したもの。完全に再現は出来てないけど、満足レベル。

GitHubにてソースを取得できます: NRBlurryStepOutAnimatedTransitioning

つかいかた

NRBlurryStepOutAnimatedTransitioning.h,mをプロジェクトに追加します。

あなたのViewControllerにUIViewControllerTransitioningDelegateプロトコルを追加:

#!objectivec
@interface NRPresentedViewController : UIViewController<uiviewcontrollertransitioningdelegate>
@end

そのViewControllerクラスに以下のような実装を加えます:

#!objectivec
#import "NRBlurryStepOutAnimatedTransitioning.h"

-(void)showNewController;
{
    UIViewController* vc = [[YourModalViewController alloc] init];
    vc.transitioningDelegate = self;
    [self presentViewController:vc animated:YES completion:NULL];
}


#pragma mark - UIViewControllerTransitioningDelegate

- (id<uiviewcontrolleranimatedtransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
    return [[NRBlurryStepOutAnimatedTransitioning alloc] initWithPresenting:YES];
}

- (id</uiviewcontrolleranimatedtransitioning><uiviewcontrolleranimatedtransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    return [[NRBlurryStepOutAnimatedTransitioning alloc] initWithPresenting:NO];
}

あとは -showNewController を好きな時に呼び出すだけ。
簡単!