プログラミングのブログ

個人的な技術メモや制作物について書く

あるViewが他のViewを再描画する

fragment にカスタム View を配置し、もう一つの fragment にその View を操作する カスタム View を配置した。
しかし、片方の View の中を invalidate() で再描画しても全体の View は再描画されなかった。
アプリ全体を再描画するものだと思っていたけど、違ったらしい。

MainActivity の layout はこうなっている。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:weightSum="4"></LinearLayout>

</android.support.constraint.ConstraintLayout>

ここに、MainActivity から、2つの Fragment (BeChangeFragment, operateFragment) を LinearLayout に追加している。
うちの環境では、こうやって動的に追加しないとなぜかアプリが落ちる。

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(savedInstanceState == null){
            FragmentManager manager = getSupportFragmentManager();
            FragmentTransaction transaction = manager.beginTransaction();
            transaction.replace(R.id.linearLayout, new BeChangeFragment());
            transaction.add(R.id.linearLayout, new OperateFragment());
            transaction.commit();
        }
        setColors();
    }
}

この BeChangeFragment の View の内容が operateFragment の View を操作したときに変更されるので、
operateFragment の View を操作したときに、BeChangeFragment の View を再描画する必要がある。
Fragment の Layout は、

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/linearLayout2"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1">

    <com.example.name.FragmentTest.BeChangeFragmentView
        android:id="@+id/be_change_fragment_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/linearLayout2"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1">

    <com.example.name.FragmentTest.OperateFragmentView
        android:id="@+id/operate_fragment_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

となっており、それぞれカスタム View の BeChangeFragmentView, OperateFragmentView を
取り込んでいる。二つの View (それを含む Fragment も) MainActivity の layout の中で同じ ViewGroup の
LinearLayout に属しているので、そこから、BeChangeFragmentView を取り出し invalidate() を呼び出し
再描画している。上記の操作をするためには、

public class OperateFragmentView extends View {
   @Override
    public boolean onTouchEvent(MotionEvent event){
        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:
                // lisner かなんかで変更をBeChangeFragmentView に伝える
                break;
            case MotionEvent.ACTION_UP:
                // lisner かなんかで変更をBeChangeFragmentView に伝える
                break;
        }
        invalidate(); // 自分の View の再描画
        getRootView().findViewById(R.id.be_change_fragment_view).invalidate(); // BeChangeFragmentView の再描画
        return true;
    }
}

と、ラストの方で、getRootView()で自分の属する ViewGroup を取得して、findViewById でBeChangeFragmentView を
ゲット、やったぜ。

Fragment とか、MainActivity のl ayout 静的に配置するとアプリが落ちて、半日以上はまったけど、できるようになってきた。
ここら辺の描画の仕方とか、タッチの処理とか システムがどう処理しているのか、View とか Fragment がどういう場所で実行され、
なにが使えるのかとか、まだまだ全然わからないよ……。Fragment に View を配置しているのは再利用をしたいと思っているから
だけど、なんか複雑にしているだけの気もする。