だてブログ

ねことテクと趣味のブログ

BottomNavigationViewを少しいじってみた①

android.support.design.widget.BottomNavigationViewは公式ライブラリのひとつです。
Bottom navigation - Components - Material design guidelines

アイコンとテキストの色を変更する(選択時、未選択時)

1. resのなかにcolorディレクトリを作る

2. そのcolorディレクトリの中にbuttom_navigation.xmlをつくり、次の内容を記載する

res/color/buttom_navigation.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true" android:color="#FFF" />
    <item android:state_pressed="true" android:color="#FFF" />
    <item android:color="#969696" />
</selector>

3. buttomnavigationviewの方に指定をする

res/layout/main.xml

...
    <android.support.design.widget.BottomNavigationView
        android:id="@+id/navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="?android:attr/windowBackground"
        app:itemBackground="@color/themecolor"
        app:itemIconTint="@color/buttom_navigation"
        app:itemTextColor="@color/buttom_navigation"
        app:menu="@menu/navigation" />
...

参考:

選択されていないタブの文字を表示させ続ける

main.java

...

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mTextMessage = (TextView) findViewById(R.id.message);
        BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
        
        // no-hide menu-text
        BottomNavigationMenuView menuView = (BottomNavigationMenuView) navigation.getChildAt(0);
        for (int i = 0; i < menuView.getChildCount(); i++) {
            BottomNavigationItemView itemView = (BottomNavigationItemView) menuView.getChildAt(i);
            itemView.setShiftingMode(false);
            itemView.setChecked(false); // Viewの状態を反映させるために呼んでいる
        }
    }

全てのタブの横幅、マージンを固定する

デフォルトの状態だと、タブ(item)が4つあると、選択されたタブのwidth(横幅)が大きく広がり、ほかが狭まる。この4つの横幅を全て固定したい。

参考:

BottomNavigationViewHelper.java

public class BottomNavigationViewHelper {
    public static void disableShiftMode(BottomNavigationView view) {
        BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
        try {
            Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
            shiftingMode.setAccessible(true);
            shiftingMode.setBoolean(menuView, false);
            shiftingMode.setAccessible(false);
            for (int i = 0; i < menuView.getChildCount(); i++) {
                BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
                //noinspection RestrictedApi
                item.setShiftingMode(false);
                // set once again checked value, so view will be updated
                //noinspection RestrictedApi
                item.setChecked(item.getItemData().isChecked());
            }
        } catch (NoSuchFieldException e) {
            Log.e("BNVHelper", "Unable to get shift mode field", e);
        } catch (IllegalAccessException e) {
            Log.e("BNVHelper", "Unable to change value of shift mode", e);
        }
    }
}

main.java

...
        mTextMessage = (TextView) findViewById(R.id.message);
        BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
        BottomNavigationViewHelper.disableShiftMode(navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
...

一般権限でWebディレクトリ外にDjangoパスを通す方法

経緯

root権限を持っていないユーザーは環境依存の強いDjangoのデプロイにとても苦労すると思います。(例えばhttpd.confでAliasを書いたり)
そこで、少し遠回りではありますが、cgiとあるライブラリを使って遠回りにDjangoパスを通す方法をここにするそうと思います。

参照

【apache】拡張子なしのファイルをCGIスクリプトとして扱う

方法

1. 上のdjango-cgiのファイルをdjangoのアプリ名と同じ名前にしてhtmlから見える位置に置く。 (例)

$ cd /var/www/
$ tree
html
├── djangoapp(元 django-python3.cgi)
└── .htaccess
djangoapp
├── djangoapp
├── manage.py
└── __init__.py       ...

2. /var/www/html/djangoapp(元 django-python3.cgi)のファイルを幾つか書き換える

(1~2行目)
#!/home/user/.pyenv/versions/envname/bin/python
# encoding: utf-8
↓↓↓↓↓
#!pythonのbinパス($ which pythonで調べる)
# encoding: utf-8

(27~30行目)
# Change this to the directory above your site code.
# sys.path.append("/home/user/local/lib/python3.4/site-packages")
# sys.path.append("/djangoproject/src")
↓↓↓↓↓
# Change this to the directory above your site code.
sys.path.append(pythonのsite-packagesのある場所)
sys.path.append(djangoアプリのある場所:/var/www/djangoapp)

(89~92行目)
# Change to the name of your settings module
os.environ['DJANGO_SETTINGS_MODULE'] = 'application.settings'
from django.core.wsgi import get_wsgi_application
run_with_cgi(get_wsgi_application())
↓↓↓↓↓
# Change to the name of your settings module
os.environ['DJANGO_SETTINGS_MODULE'] = 'djangoapp.settings' ← アプリ名
from django.core.wsgi import get_wsgi_application
run_with_cgi(get_wsgi_application())

3. .htaccess (/var/www/html/.htaccess)を編集(下を追加)

<FilesMatch "^[^\.]+$">
    SetHandler cgi-script
</FilesMatch>

4. djangoのstaticファイルをhtmlから見える位置に置き、settings.pyのSTATIC_URL, STATIC_ROOTも変更

やらかした-滅びの呪文

突然だが"滅びの呪文"というのをご存知だろうか。黒い画面で管理者権限でログインして、
rm -Rf /” と打つと
………
はい、今回はわたしも滅びの呪文を打ってしまった経緯をお話しする。私はこのようなディレクトリ構成で作業をしていた。

username
├── testA
│   ├── test2
│   ├── test3
│   │   ├── testa
│   │   ├── testb
│   │   └── ~username
│   └── test4

“test3"に私はいた。そして”~username"というフォルダが間違えて作られたものだということに気づいた私は、
rm -Rf ~username” と打ってしまった。お気付きの方もいるであろうか 。"~“はホームディレクトリを指す。それは上の図の一番上、”~username"を指す。つまり、上のコマンドを押すと……

username
└──

全て消えた。
今までの作業。
すべて。

自分にはroot権限がないため、管理者にrmしたものを復活させる邪道なプログラムを入れてもらうよう頼んだが、、ダメでした。(リスクもあるため) 原則的にrmしたものは復活できない。それを心から感じました。結局、ローカルやgithubなどに保存したものと他のユーザを参考にして、半分ほどは復活させることができました。
次からは次のファイルをcron使って定期的に打ってバックアップを取ることにします。

#!/bin/bash
chmod 777 ~/.backup 2> /dev/null
rm ~/.backup/backup.gz 2> /dev/null
shopt -s dotglob
tar cfz ~/.backup/backup.gz * 2> /dev/null
chmod 400 ~/.backup