AndroidのExpandableListViewとRecyclerView

結論からして相性が良くない。requestLayoutとか入れて実験してみたけど、できなかった。

やりたかったこと

RecyclerView>CardView>ExpandableListViewっていうのをやってコストを下げたかった。

やってみた

そのまま実装してみるとだめだったので、RecyclerView>ExpandableListViewをやってみたらこの時点でダメだった。f:id:b1u3:20180616211355p:plain
wrap_contentがうまくいかない。Android developers見てみたらwrap_contentはダメだぞって書いてあった。ExpandableListViewのGroupViewのonClickにRecyclerViewのrequestLayout()を入れてもダメだった(実装が悪い?)

妥協案

愚直にLinearLayoutにぶち込んだ。この分ならRelativeでも大丈夫な気がする。
f:id:b1u3:20180616211730p:plain

AndroidのFragmentのreplace

最近またAndroidやってます。ノリで書いてたら詰まったのでちょっとしたメモです。

動的なFragment

Google developersに載ってるようなタグを使ってxmlを使うと動的にFragmentを差し替えることができない。

解決法

googleの画面を1:2に配分してそれぞれに動的なフラグメントを割り当てたいとき、googleのコードのを適当なViewGroupに変更する。つまり、

<?xml version="1.0" encoding="utf-8"?>
<!-- activity_main.xml -->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:id="@+id/fragment_container"
    >
    <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:id="@+id/fragment_list_container"
            />
    <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:id="@+id/fragment_content_container"
            />
</LinearLayout>
/*
MainActivity.java
*/
package com.b1u3dev.fragmentandlayout;

import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;


public class MainActivity extends AppCompatActivity {
    private FragmentManager mFragmentManager;
    private String className=MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mFragmentManager=getSupportFragmentManager();
        mFragmentManager.beginTransaction().add(R.id.fragment_content_container,new ContentFragment()).commit();
        mFragmentManager.beginTransaction().add(R.id.fragment_list_container,new ListFragment()).commit();

    }

 
    public void onClick(View view){
        Log.d(className,"Fragment Size:"+mFragmentManager.getFragments().size());
        switch (view.getId()){
            case R.id.content_button:
                Log.d(className,"content_button was clicked");
                mFragmentManager.beginTransaction().replace(R.id.fragment_content_container,new SecondContentFragment()).commit();
                break;
            case R.id.list_button:
                Log.d(className,"list_button was clicked");
                break;
        }

    }
}

こんな感じで。
xxxFragmentは全部FragmentのサブクラスでonCreateViewをオーバーライドしてinflateしてる。
f:id:b1u3:20180615030417p:plain

その他のファイル

package com.b1u3dev.fragmentandlayout;
/*
ContentFragment.java
 */

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class ContentFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_content,container,false);
    }
}
package com.b1u3dev.fragmentandlayout;
/*
ListFragment.java
 */

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class ListFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_list,container,false);
    }
}
package com.b1u3dev.fragmentandlayout;
/*
SecondContentFragment.java
 */

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class SecondContentFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_content_second,container,false);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<!-- fragment_content.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Test Content"/>
    <Button
            android:id="@+id/content_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Content Fragment Button"
            android:onClick="onClick"/>

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- fragment_content_second.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="SECOND FRAGMENT CONTENT BUTTON"/>
    <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="SECOND FRAGMENT CONTENT BUTTON"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- fragment_list.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent">
        <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="List Activity"/>
        <Button
                android:id="@+id/list_button"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="List Activity Button"
                android:onClick="onClick"/>

</LinearLayout>

あ、ボタンの名前修正するの忘れてた。

java 10.0.1 と Intelli J Idea

Intelli J Idea と java 10.0.1 と Android用の 8 の共存やってみた。萌黄えもなので。
普通に入れて設定したら

could not determine java version using executable ...

というのがsync failedと一緒に出てきた。
OS X の方はbrewでgradleをupgradeして、Intelli J のpreference>Build Tools>gradleからUse local gradle distributionにチェック。からのGradle homeに適切なlibexecを登録する。
Windowsの方は設定はsettingsから。ちなみに OS Xの方はdefault settingsから設定できない。

pythonのエントリーポイント

経緯

割と唐突にpythonソースコードを読んでみたくなったので、ちょっと覗いてみた。

今回の目的

インタープリターのエントリーポイントが見つかるまで。

探す

エントリーポイントっていうのはmain関数(UNIX/Linux)とwmain関数(windows)のことをここでは指す。_startではないです。pythonのcpythonリポジトリを最初に見ると、いろいろディレクトリがある。ひとつひとつ見たり、単語検索かけるのはあまり勉強味がないので、ある程度の推測とかを駆使して見つけていった。はじめにそのリポジトリを見るとインストール方法とかが載ってるREADME.rstが下部に表示されている。
UNIX系だと

./configure
make
make test
sudo make install

のような一般的なインストール方法になっている。

./configure

いうのは同ディレクトリ内のMakefile.pre.inというファイルをもとにした環境に適したmakefileを出力するスクリプト。これはautoconfというAutotoolsという一連の開発ツールの一つによって出力されたファイル。2万行ちかくあった。Makefile.pre.inを見れば、主な流れがわかる。

Makefile.pre.inを見てみる。最初の方には変数とか定数の定義が書かれている。これはmakefileの構文に従う。後半にmekefile特有のルールとかターゲットとかが書かれている。基本的にはallターゲットが実行されるので、all:ではじまる部分を見る。この部分は見てみると@で囲まれた単語があるので、ここは./configureで置換される部分。よって、ここだけではわからんみたいな。
読み進めていくと、コメントで

#Build the interpreter

の行があるので、インタープリターをビルドしてるんだなってわかる。んで、直後に$(BUILDPYTHON)っていうのがあるので、これがビルドされるプログラムの名前なのかなみたいな。だからもう少しみる。Programs/python.oというのが必要らしい。なんか重要っぽいなって思ったのでPrograms/python.cを見てみるとmainがあった。

結論

Programs/python.cにあるよ。

gitサーバーをおったてた

LAN内にいろいろなパソコンがあってソースコードの共有とかがめんどくさかったので、gitサーバーを立てました。メモと手順(自分用)

続きを読む

Arch Linux ARMを入れた

ブログを続けようと思ってたら、半年以上空けてしまいました。9月半ばぐらいに2つほど書いたんですけど完成しませんでした。下書きには残ってるんですけど、長くなりそうで続きを書きたくないのが本音です。今回は日記です。教えることはないです。

本題

gitサーバーが欲しいなって思って2年前に買ったラズパイmodel Bを取り出して作ってみることにしました。なんのOS入れようかなと思ってたところ、丁度Arch Linuxにはまっているので、Arch Linux ARMをいれることにしました。

続きを読む