DOCTYPE

<!DOCTYPE>は、正式にはHTMLタグではないらしい。
ドキュメントタイプ宣言というもので、HTMLのバージョンを表している。

<!DOCTYPE> - ドキュメントタイプ - とほほのWWW入門

まず、

$ vi DOCTYPE.html
$ cat DOCTYPE.html
<html>
  <head>
    <title>!DOCTYPE</title>
  </head>
  <body>
    !DOCTYPE
  </body>
</html>
$ 

何も付けない。
IE11の開発者ツール(F12)を起動すると、

指定する必要があるとの警告
指定する必要があるとの警告

指定する必要があるとの警告。

$ vi DOCTYPE.html
$ cat DOCTYPE.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <title>!DOCTYPE</title>
  </head>
  <body>
    !DOCTYPE
  </body>
</html>
$

HTML4.01以前の指定。

まあHTML5ではないからね。
まあHTML5ではないからね。

まあHTML5ではないからね。

この形式なら、

HTML5なので警告は消える
HTML5なので警告は消える

HTML5なので警告は消える。

Sample/html/DOCTYPE/DOCTYPE/src/DOCTYPE at master · bg1bgst333/Sample · GitHub

RecyclerView.Adapter

RecyclerViewで、リスト表示して、スクロール連携するには、ViewHolderとAdapterが必要。

RecyclerView.Adapter  |  Android Developers
Androidのマテリアルデザイン ~リサイクラービュー~ (3/3):CodeZine(コードジン)

まず、ViewHolder。

RecyclerView.ViewHolderから継承して、今回はTextViewは1つでいい。
今回は、コンストラクタで既定のandroid.R.id.text1からview.findViewByIdで取得したTextViewを自身のメンバmtvNameに格納する。
次に、CustomAdapter。

RecyclerView.Adapter<CustomViewHolder>から継承。
ListのアイテムはStringで。
onCreateViewHolderで、既定のandroid.R.layout.simple_list_item_1からinflater.inflateしてviewを作成。
CustomViewHolderのコンストラクタに渡して、customViewHolder自身を返す。
onBindViewHolderで、アイテムであるStringなitemを取得し、holder.mtvNameにセット。
ということで、今回は独自なレイアウトはなし。
MainActivity.javaは、

linearLayoutManagerを生成し、recyclerview1.setLayoutManagerでセットしないと、リスト形式にならないし、そもそも表示がされない。

起動時
起動時

起動時。

下に行くと小さくなる
下に行くと小さくなる

下に行くと小さくなる。

ここで止まる
ここで止まる

ここで止まる。

戻せばまた大きく
戻せばまた大きく

戻せばまた大きく、

先頭に戻ると、この大きさに戻る
先頭に戻ると、この大きさに戻る

先頭に戻ると、この大きさに戻る。

Sample/android/RecyclerView.Adapter/RecyclerView.Adapter/RecyclerView.Adapter_ at master · bg1bgst333/Sample · GitHub

RecyclerView

RecyclerViewは、Toolbarのスクロール連動など、マテリアルな動きに対応した、リストビューに代わるビュー。

RecyclerView  |  Android Developers
Androidのマテリアルデザイン ~リサイクラービュー~ (1/3):CodeZine(コードジン)

strings.xmlは、

あのlongなtextはもう無い。
activity_main.xmlは、

NestedScrollViewを配置していたところに、今回はRecyclerViewを配置。
MainActivity.javaは、

今回は、配置したRecyclerViewをfindViewByIdで取得して、存在を確認するだけ。

確かに存在する
確かに存在する

確かに存在する。

Sample/android/RecyclerView/RecyclerView/RecyclerView_ at master · bg1bgst333/Sample · GitHub

ViewHolder

前回のように、文字列などデータをセットするViewの参照をあらかじめ保持しておきたい場合で、1アイテムに複数のビューの場合は、ViewHolderを使う。

【Android】ViewHolderパターンの使い方|IT小人の前進

ViewHolderというクラスが定義されてるわけじゃなくて、自分で作成する。

今回は2つのTextView。
ViewHolder.javaは、

2つのTextView。
ListItem.javaは、

こっちはどちらもString。
CustomAdapter.javaは、

viewHolderの持つ2つのTextViewに、convertView.findViewByIdで探した2つのTextViewをそれぞれ渡しておいてviewHolderをsetTag。
nullでなければ、getTagでviewHolderを取得できる。
MainActivity.javaは、

1万個用意。

起動時
起動時

起動時。

どうだろう。動かしてもわからん。
どうだろう。動かしてもわからん。

どうだろう。動かしてもわからん。
まあ、ViewHolderは、この後にも繋がる話なので。

Sample/android/patternViewHolder/patternViewHolder/src/patternViewHolder at master · bg1bgst333/Sample · GitHub

View.getTag

View.getTagで、ビューにセットしておいたタグを取得する。

View  |  Android Developers

今回はListViewの中で使う。
list_item.xmlで、

LinearLayoutの中にTextViewというアイテム。
activity_main.xmlは、

ListView。
CustomAdapter.javaで、

package com.bgstation0.android.sample.view_;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

// カスタムアダプタ
public class CustomAdapter extends ArrayAdapter<String> {

	// メンバフィールドの定義.
	private final LayoutInflater mInflater;	// インフレータmInflater.
	
	// コンストラクタ.
	public CustomAdapter(Context context, int textViewResourceId, List<String> objects) {
		super(context, textViewResourceId, objects);
		// TODO Auto-generated constructor stub
		mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);	// mInflaterを生成.
	}

	// アイテム表示のカスタマイズ
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// convertViewがnullの時.
		if ( == null){
			convertView = mInflater.inflate(R.layout.list_item, null);	// convertViewがnullならinflater.inflateで取得.(ここは難しいのでひとまずこういうものだと捉えておく.)
		}
		TextView liTextView = (TextView)convertView.findViewById(R.id.list_item_textview);	// convertView.findViewByIdでR.id.list_item_textviewをliTextViewに格納.
		liTextView.setText(getItem(position));	// position番目のアイテムをliTextView.setTextでセット.
		return convertView;	// convertViewを返す.
	}
	
}

引数のconvertViewがnullの時は再生成が必要なので、mInflater.inflateの結果のViewをconvertViewに格納。
convertView.findViewByIdでliTextViewを探してそれに現在位置のテキストをセット。

アイテム1万個用意。

起動時
起動時

起動時。
動かしてみる。

どうだろうか。もっさりするかはわからない。
どうだろうか。もっさりするかはわからない。

どうだろうか。もっさりするかはわからない。
要はアイテムが多すぎると、convertView.findViewByIdは時間かかるので、パフォーマンスに影響が出るかもということ。

convertViewがnullなら、再生成が必要なので、mInflater.inflateとconvertView.findViewByIdしないといけない。
で、それが終わったら、convertView.setTagでliTextViewをタグとしてセットする。
nullでなければ、再生成不要だから、convertView.getTagでliTextViewを取得できるし、それにテキストをセットするだけでいい。
convertViewがいれば、liTextViewもいるわけだから、liTextViewの参照を取得出来れば、わざわざfindViewByIdする必要もない。

どうだろうか
どうだろうか

どうだろうか。
動かしてみる。

わからない
わからない

わからない。
でもアイテムがもっと大量にあった場合のパフォーマンスには影響しそう。

Sample/android/View/getTag/src/View at master · bg1bgst333/Sample · GitHub

View.setTag

View.setTagで、ビューにタグをセットできる。

View  |  Android Developers

いろいろな使い方があるが、今回はボタンに文字列としてのタグを付けて、クリック時にどちらが押されたかを判定する。
strings.xmlで、

このようにして、activity_main.xmlで、

Buttonを2つ用意。
MainActivity.javaは、

button1にTAG_BUTTON_1("tag_button_1")、button2にTAG_BUTTON_2("tag_button_2")をView.setTagで付けて、onClick時にView.getTagで取得したタグが、どちらなのか判定してる。

起動時
起動時

起動時。
Button1を押すと、

こう出るので、TAG_BUTTON_1が取得出来てる。
こう出るので、TAG_BUTTON_1が取得出来てる。

こう出るので、TAG_BUTTON_1が取得出来てる。
Button2を押した時も、

こう出るので、TAG_BUTTON_2が取得出来てる
こう出るので、TAG_BUTTON_2が取得出来てる

こう出るので、TAG_BUTTON_2が取得出来てる。

Sample/android/View/setTag/src/View at master · bg1bgst333/Sample · GitHub

CollapsingToolbarLayout

スクロールの動きとToolbarの表示の連動の仕方にはいろいろある。
前回のように、activity_main.xmlで、

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Toolbar
            android:id="@+id/toolbar1"
            android:layout_width="match_parent"
            android:layout_height="?android:attr/actionBarSize"
            android:background="@color/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways" />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <TextView
            android:id="@+id/textview_longtext"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/textview_longtext_text" />

    </android.support.v4.widget.NestedScrollView>

</android.support.design.widget.CoordinatorLayout>

AppBarLayoutでapp:layout_scrollFlags="scroll|enterAlways"の場合は、

1番下まで行って
1番下まで行って

1番下まで行って、上に戻ろうとすると、

すぐToolbarが出てくる
すぐToolbarが出てくる

すぐToolbarが出てくる。
どんな位置からでも上に戻ろうとしたときにToolbarが連動して出てくる。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Toolbar
            android:id="@+id/toolbar1"
            android:layout_width="match_parent"
            android:layout_height="?android:attr/actionBarSize"
            android:background="@color/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlwaysCollapsed" />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <TextView
            android:id="@+id/textview_longtext"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/textview_longtext_text" />

    </android.support.v4.widget.NestedScrollView>

</android.support.design.widget.CoordinatorLayout>

しかし、app:layout_scrollFlags="scroll|enterAlwaysCollapsed"にすると、

下まで行って
下まで行って

下まで行って、上に戻っても、

出てこない
出てこない

出てこない。

リストの1番上のところまで戻って初めて出てくる
リストの1番上のところまで戻って初めて出てくる

リストの1番上のところまで戻って初めて出てくる。
スクロールにはもうひとつ、

app:layout_scrollFlags="scroll|exitUntilCollapsed"

というフラグがあるが、これはCollapsingToolbarLayoutで使う。

CollapsingToolbarLayout  |  Android Developers
Androidのマテリアルデザイン ~スクロール連動~ (2/3):CodeZine(コードジン)

これらを使うと、Toolbarを伸縮しつつ、一定のところで止める事ができる。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar1"
        android:layout_width="match_parent"
        android:layout_height="200dp" >

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed" >

            <Toolbar
                android:id="@+id/toolbar1"
                android:layout_width="match_parent"
                android:layout_height="?android:attr/actionBarSize"
                android:background="@color/colorPrimary"
                app:layout_collapseMode="pin" />

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <TextView
            android:id="@+id/textview_longtext"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/textview_longtext_text" />

    </android.support.v4.widget.NestedScrollView>

</android.support.design.widget.CoordinatorLayout>

AppBarLayoutで200dpにすることで、最初の高さは200dpになる。
CollapsingToolbarLayoutを中に入れて、そちらにapp:layout_scrollFlags="scroll|exitUntilCollapsed"を指定。
Toolbarでapp:layout_collapseMode="pin"を指定。
一番小さくなった時の高さは、android:layout_height="?android:attr/actionBarSize"に基づくから、Toolbarのデフォルトの高さのはず。

最初は200dpだからこれぐらい大きくなる
最初は200dpだからこれぐらい大きくなる

最初は200dpだからこれぐらい大きくなる。

下に行くとどんどん小さくなる
下に行くとどんどん小さくなる

下に行くとどんどん小さくなる。

あれ?止まらない・・・。
あれ?止まらない・・・。

あれ?止まらない・・・。

消えてしまった・・・。
消えてしまった・・・。

消えてしまった・・・。
本当ならToolbarの高さより小さくはならないようにどこも書いてあるのだが・・・。

いろいろなCoordinatorLayoutパターン - Qiita

上記の記事などいろいろ見たけど、

android:minHeight="?android:attr/actionBarSize"を付けたら、

ここから
ここから

ここから、

小さくなって
小さくなって

小さくなって、

ここからは小さくならなくなった
ここからは小さくならなくなった

ここからは小さくならなくなった。
でも、付けてない記事もあるので何が違うのだろうか・・・。

Sample/android/CollapsingToolbarLayout/CollapsingToolbarLayout/CollapsingToolbarLayout_ at master · bg1bgst333/Sample · GitHub