RecyclerView in NestedScrollViewでスクロールが角つく

javaコード中で、次を追加すると回避できた.
1
recyclerView.setNestedScrollingEnabled(false);

しかし、そもそもNestedScrollViewとRecyclerViewをネストにすることが問題っぽい.
例えば、画面をスクロールしてもRecyclerView.onScrolledは呼ばれないみたいなので、ネストするというデザインを変えたほうがいいかもしれない.

参考にしたサイト



CheckBoxのチェックボックスを右側に表示させる。

題名の日本語が少し怪しい感じがするが、CheckBoxはデフォルトでは次のようになる.


これを次のようにするのが当記事の目的である.


API 17以上の場合


xmlの方で、CheckBoxlayoutDirction属性をrtlにしてやるだけ.
1
android:layoutDirection="rtl"


API 17未満の場合


同じくxmlの方で、CheckBoxに、次の2つを加える.
1
2
android:button="@null"
android:drawableEnd="?android:attr/listChoiceIndicatorMultiple"

ただ、この方法だとCheckBoxをクリックしたとき、チェックボックスではなくCheckBoxの中心がハイライトされるので注意(下の画像を参照).



参考にしたサイト



BloggerにSyntaxHighlighterを導入する!

SyntaxHighlighter v3は導入できなかったが、最新のSyntaxHighlighter v4を導入できたので、その方法を紹介したいと思う.
SyntaxHighlighterを導入できずに諦めている人にぜひ読んでもらい、私と同じ喜びを感じてほしいと思う.

導入する!



その0


Git Bash(Windowsの場合)Node.js(LTSのほうが良い?)をインストールする.

その1


Git Bushを起動して、syntaxhighlighterを保存するローカルディレクトリに移動し、以下のコードを続けて入力する.
1
2
3
$ git clone https://github.com/syntaxhighlighter/syntaxhighlighter.git
$ cd syntaxhighlighter
$ npm install

次のような感じ




その2


続いて、以下のコードを入力する.
1
2
ko-ika@PC MINGW64 ~/Blogger/syntaxhighlighter (master)
$ ./node_modules/gulp/bin/gulp.js setup-project

そのまま通れば(その3へ)問題ないが、次のエラーが出るかもしれない.(私の場合はこうなった.)
1
[hh:mm:ss] TypeError: loadReposFromCache(...).error is not a function

この時は、 /syntaxhighlighter/build/setup-project.js を開いて、39行の error catch に変える.
つまり、39行目を次のようにして上書き保存する.
39
const loadRepos = () => loadReposFromCache().catch(loadReposFromGitHub).then(R.map(R.pick(['clone_url', 'name'])));

そして、Git Bashで、その2の初めのコードを再び入力する(うまくいくはず).

無事成功すると、 /syntaxhighlighter/repos/ 下に新たなファイルフォルダーがダウンロードされる.



その3


次に、 ./node_modules/gulp/bin/gulp.js build を使う.

この時に、 --brushes --theme を指定する.


--brushes


Xという言語をハイライトさせたいのなら、 --brushes=X という風にする.

コンマで区切ることで複数指定することもできる: --brushes=X,Y

どの言語が対応しているかは、 /syntaxhighlighter/repos/ 下にある brush-X という名前のフォルダーを探せばわかる(Xには、具体的な言語が入る、javascriptとか).

また、 --brushes=all とすれば、 /syntaxhighlighter/repos/ 下にある言語すべてをハイライトできる.


--theme


Xというテーマを使いたかったら、 --theme=X という風に指定する。

使用できるテーマは、以下のサイトに載ってる(多分).


次のサイトは、画像もあって役に立つ.


/syntaxhighlighter/repos/ 下にあるフォルダー theme-X を探してもらえば、対応しているテーマが分かる.

使用例


例えば、javascriptとcssをハイライトさせたくて、テーマはdefaultにしたい場合、Git Bashに次のように入力する.
1
2
ko-ika@PC MINGW64 ~/Blogger/syntaxhighlighter (master)
$ ./node_modules/gulp/bin/gulp.js build --brushes=javascript,css --theme=default

これが通れば問題ないので、その6まで行ってほしいが、次のエラーが出るかもしれない. 多分出る.
1
[hh:mm:ss] TypeError: Promise.props is not a function


その4


/syntaxhighlighter/build/bundle.js を開いて、33行目の 'songbird' 'bluebird' に変えて、上書き保存する.
33
const Promise = require('bluebird');

そして、再び ./node_modules/gulp/bin/gulp.js build --brushes=javascript,css --theme=defaultを走らせる.


上の画像のように、次のようなエラーが発生すると思う(もし、うまくいったらその6まで飛んでもらいたい).
1
2
3
ERROR in ./src/core.js
Module not found: Error: Cannot resolve module 'brush-javascript' in C:\Users\ko-ika\Blogger\syntaxhighlighter\src
 @ ./src/core.js 241:14-41


その5


上のエラー中の、Module not found: Error: Cannot resolve module 後の2つの'で囲まれたファイルフォルダーを手動でインストールする.
1
2
ko-ika@PC MINGW64 ~/Blogger/syntaxhighlighter (master)
$ npm install folder-name

上の例では、以下のようにする.
1
2
3
4
5
ko-ika@PC MINGW64 ~/Blogger/syntaxhighlighter (master)
$ npm install brush-javascript
 
ko-ika@PC MINGW64 ~/Blogger/syntaxhighlighter (master)
$ npm install brush-css

そして、 ./node_modules/gulp/bin/gulp.js buildを走らせる.

特にエラーは出ないで、終了すると思う.

もし、うまくいかなかったら、次も試してみる.
1
2
3
4
npm install opts-parser
npm install syntaxhighlighter-match
npm install syntaxhighlighter-html-renderer
npm install syntaxhighlighter-regex


その6


syntaxhighlighter/dist ディレクトリ下にいくつかのファイルが生成されているが、その中の、 syntaxhighlighter.js theme.css を各自のサーバーにアップロードする。

あとは、ブログのHTMLをいじるだけ(ここから先は、こちらの記事のその2と似ている).

Boggerのトップページのサイドメニューの「レイアウト」をクリックし、「HTML編集」ボタンを押す.


</head>タグの上に以下のコードを挿入する.

1
2
<script src='[path]/syntaxhighlighter.js' type='text/javascript'/>
<link href='[path]/theme.css' rel='stylesheet' type='text/css'/>

コード中の[path]は、syntaxhighlighter.jsと、theme.cssをアップロードしたフォルダー名を指定する. 同じフォルダーでなくてもよい. 例えば、https://foo.com/styles/theme.csshttps://foo.com/scripts/syntaxhighlighter.jsなど.


そして、「テーマを保存」ボタンを押すだけ.


使用方法・注意点


使い方は、基本的に前のバージョンのSyntaxHighlighterとかわらないっぽいので、他のサイトを見てもらいたい.

一つだけ注意することは、この方法で導入したハイライターにはデフォルトでツールバーが表示されないことだ.


参考にしたサイト






ColorFilterを元に戻す

方法は2つ見つかった.

その1
  1. EditText editText = findViewById(R.id.editText);
  2.  
  3. editText.getBackground().clearColorFilter();


その2
  1. EditText editText = findViewById(R.id.editText);
  2.  
  3. editText.getBackground().setColorFilter(null);


うまくいかなかったら、この後に次を入れる.
  1. editText.refreshDrawableState();


参考にしたウェブサイト

ConstraintLayoutの制約をJavaで設定する

ConstraintLayout#LayoutParamsを使う. まず、ConstraintLayout上のViewを取得する.
  1. Button button = findViewById(R.id.button);

もしくは、追加したい適当なオブジェクトを作成し、ConstraintLayoutにViewを追加する.
  1. Button button = new Button(this);
  2. constrintLayout.addView(button)

※先にaddViewしないと、次のlayoutParamsにnullが入る(エラーが発生する)ので注意.

次に、上のViewのLayoutParamsを取得し、適当に設定する. 親View(?)と連結したいときは、PARENT_IDを代入する. ほかのViewと連結したいときは、View#getIdメソッドを使う. LayoutParamsのフィールドについては、xmlのものとほとんど同じなので、そちら(例えば、Android Studioのデザインビューとか)を見るとわかりやすいと思う.
  1. ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams)button.getLayoutParams();
  2. layoutParams.startToEnd = anotherView.getId();
  3. layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
  4. layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID;
  5. layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID;
  6. layoutParams.verticalBias = (float) 0.1;
  7. layoutParams.horizontalBias = (float) 0.1;
  8. button1.setLayoutParams(layoutParams);

最後に、上の変更を適用する.
  1. button.setLayoutParams(layoutParams);

他にもこちらと同様に、ViewのWidthやHeight、Marginを変更できたりする(MarginLinearLayoutにキャストしなくてもよい、次の適用例を参照).

適用例


ConstraintLayout上に2つのボタンを表示させる.

activity_main.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:id="@+id/constraintLayoutParamsLayout"
  6. android:layout_width="match_parent"
  7. android:layout_height="match_parent"
  8. tools:context="com.blogspot.ko-ika.constraintlayoutparams.MainActivity">
  9.  
  10. <Button
  11. android:id="@+id/button1"
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:text="Button1" />
  15.  
  16. <Button
  17. android:id="@+id/button2"
  18. android:layout_width="wrap_content"
  19. android:layout_height="wrap_content"
  20. android:text="Button2" />
  21. </android.support.constraint.ConstraintLayout>

activity_main.xml
  1. package jp.blogspot.ko-ika.constraintlayoutparams;
  2.  
  3. import android.support.constraint.ConstraintLayout;
  4. import android.support.v7.app.AppCompatActivity;
  5. import android.os.Bundle;
  6. import android.widget.Button;
  7.  
  8. public class MainActivity extends AppCompatActivity {
  9.  
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_main);
  14.  
  15. Button button1 = findViewById(R.id.button1);
  16. Button button2 = findViewById(R.id.button2);
  17.  
  18. ConstraintLayout constraintLayout = findViewById(R.id.constraintLayoutParamsLayout);
  19.  
  20. // Button1の設定
  21. ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams)button1.getLayoutParams();
  22. layoutParams.topMargin = 8;
  23. layoutParams.rightMargin = 16;
  24. layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
  25. layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
  26. layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID;
  27. layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID;
  28. layoutParams.verticalBias = (float) 0.1;
  29. layoutParams.horizontalBias = (float) 0.1;
  30. button1.setLayoutParams(layoutParams);
  31.  
  32. // Button2の設定
  33. layoutParams = (ConstraintLayout.LayoutParams)button2.getLayoutParams();
  34. layoutParams.leftMargin = 16;
  35. layoutParams.startToEnd = button1.getId();
  36. layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
  37. layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID;
  38. layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID;
  39. layoutParams.verticalBias = (float)0.1;
  40. layoutParams.horizontalBias = 0;
  41. button2.setLayoutParams(layoutParams);
  42. }
  43. }

実行例


さらに


ConstraintSetを使うと同じ様に設定できるらしい.


が、この方法だと、Biasが設定できない?

また、Viewが実際に配置される(?)まで、そのIDが取得できないみたいなので、注意が必要.
実際に、上の適用例を次のようにしてみる.

activity_main.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:id="@+id/constraintLayoutParamsLayout"
  6. android:layout_width="match_parent"
  7. android:layout_height="match_parent"
  8. tools:context="com.blogspot.ko-ika.constraintlayoutparams.MainActivity">
  9.  
  10. </android.support.constraint.ConstraintLayout>

activity_main.xml
  1.  
  2. Button button1 = new Button(this);
  3. Button button2 = new Button(this);
  4. ConstraintLayout constraintLayout = findViewById(R.id.constraintLayoutParamsLayout);
  5.  
  6. // Button1の設定
  7. constraintLayout.addView(button1);
  8. button1.setText("Button1");
  9. ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams)button1.getLayoutParams();
  10. layoutParams.topMargin = 8;
  11. layoutParams.rightMargin = 16;
  12. layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
  13. layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
  14. layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID;
  15. layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID;
  16. layoutParams.verticalBias = (float) 0.1;
  17. layoutParams.horizontalBias = (float) 0.1;
  18. button1.setLayoutParams(layoutParams);
  19.  
  20. // Button2の設定
  21. constraintLayout.addView(button2);
  22. button2.setText("Button2");
  23. layoutParams = (ConstraintLayout.LayoutParams)button2.getLayoutParams();
  24. layoutParams.leftMargin = 16;
  25. layoutParams.startToEnd = button1.getId();
  26. layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
  27. layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID;
  28. layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID;
  29. layoutParams.verticalBias = (float)0.1;
  30. layoutParams.horizontalBias = 0;
  31. button2.setLayoutParams(layoutParams);

変更箇所をマークアップした. すると、次のようになってしまう.

参考にしたサイト



removeViewが動かない

ViewGroup#removeViewメソッドの引数がnullでないのにnullだったため、動かなくなった.

まず、引数がnullかどうか確かめよう(引数をnullにしても例外が発生しないので気づかなかった).
以下の方法は、消去したいViewに変数を割り当てなくてもできる方法である

コードは以下のようである.
  1. parentLinearLayout.removeView(childLinearLayout);

どうも描画中のアニメーションのせいで、動かないらしい.


上記サイトの方法だと、LinearLayoutを継承したクラスを作って、削除するときのアニメーションを表示させないようにしているようだ.

この方法だとかなりの手間がかかりそうだったので、代わりにViewGroup#removeViewAtメソッドを使ったところ、うまくいった.
  1. parentLinearLayout.removeViewAt(index);

indexとしてchildLinearLayoutのポジションを指定する.

ちなみに、子Viewのindexを取得するには、ViewGroup#indexOfChildメソッドを使う.
  1. int index = parentLinearLayout.indexOfChild(childLinearLayout);

参考にしたサイト


LinearLayoutのサイズをJavaコード中で変更する

タイトルにある通り

LinearLayoutでは、setHeight等が使えないので、android.view.ViewGroup.LayoutParamsを使う.
  1. LinearLayout linearLayout = findViewById(R.id.LinearLayout);
  2. ViewGroup.LayoutParams layoutParams = linearLayout.getLayoutParams();
  3.  
  4. layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
  5. layoutParams.width = 200;
  6.  
  7. ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams)linearLayout.getLayoutParams();
  8.  
  9. marginLayoutParams.leftMargin = 8;
  10. marginLayoutParams.rightMargin = 8;
  11. marginLayoutParams.topMargin = 8;
  12. marginLayoutParams.bottomMargin = 8;
  13.  
  14. linearLayout.setLayoutParams(marginLayoutParams);


単位は、pixelだそう. dip(dp)を使いたい場合は、例えば、5行目を
  1. layoutParams.width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200, getResources().getDisplayMetrics());


とする. (試してない.)

この方法は、ConstraintLayoutや、ImageButton等でも使えるっぽい.

参考にしたウェブサイト

FloatingActionButtonをスクロール中に消す

NestedScrollView を下にスクロールしている間は, FloatingActionButton を表示させないようにする. 少し変えれば, RecyclerView 等の他のScrollViewにも使えそう(未確認). 下に実際の挙動を示した. 目次 ...