これは、いくつかの理由で実際に他の人にとって役立つ場合があります。
プログラムコンストラクターを介して必要な方法でのみ構成できるビューを使用する必要がある場合 (たとえば、 activity_main.xml からビューを含めるだけで済みますが、次の場合を除き、ビューは必要なものではありません) OSMDroid の MapView を使用したオフライン タイル マップのように、自分で構築する場合)、その View を拡張し、AttributeSet を含むその View のコンストラクターを実装することになります。AttributeSet は基本的に、そのビューの activity_main.xml xml から解析された構造です。そのコンストラクターは、onCreate() から this.setContentView(R.layout.activity_main) を実行すると、Activity で自動的に呼び出されます。そのため、カスタム コンストラクターはすべて、拡張ビューのコンストラクターに入れる必要があります。
たとえば、OSMDroid MapView を拡張してから、スーパーからオフライン マップ タイル ソースを完全に実装する必要がありました。継承されたコンストラクターが完了するまでオブジェクトメソッドを使用できないため、拡張コンストラクターの最初の行を super() する必要があることに注意してください。
public class FieldMapView extends MapView {
public FieldMapView(Context context, AttributeSet attrs) throws Exception {
super(
context,
256,
new DefaultResourceProxyImpl(context),
FieldMapView.getOfflineMapProvider(context, MainActivity.mapTileArchiveFilename),
null,
attrs);
this.setUseDataConnection(false);
this.setBuiltInZoomControls(false);
this.setMultiTouchControls(true);
}
次に、私の activity_main.xml で、View の拡張バージョンを指定します (例: FieldMapView)。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rootview"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<com.test.FieldMapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="false"/>
これで、拡張された View がプログラム スタイルの要件を処理できるようになりました。SlidingDrawer をそれと連携させるにはどうすればよいでしょうか? 0dip の高さのビューをハンドルとして SlidingDrawer を作成しました。次に、ボタンなど、必要なものを含む LinearLayout を含めました...
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rootview"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<com.test.FieldMapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="false"/>
<SlidingDrawer
android:layout_width="wrap_content"
android:id="@+id/slidingDrawerActions"
android:content="@+id/action_content"
android:padding="10dip"
android:layout_height="75dip"
android:handle="@+id/handle2"
android:layout_alignBottom="@id/mapview"
android:orientation="vertical"
android:clickable="false">
<LinearLayout
android:layout_width="wrap_content"
android:id="@+id/action_content"
android:orientation="horizontal"
android:gravity="center"
android:padding="10dip"
android:background="#FF999999"
android:layout_height="wrap_content"
android:clickable="false">
<View
android:id="@id/handle2"
android:layout_width="0dip"
android:layout_height="0dip" />
<ImageButton
android:id="@+id/chatActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="2dip"
android:src="@drawable/ic_action_edit"
android:text="Chat">
</ImageButton>
</LinearLayout>
</SlidingDrawer>
</RelativeLayout>
私の MainActivity onCreate() では、SlidingDrawer ビューを見つけて、それに応じてリスナーを割り当てます。MapView でマーカーを長押ししたときにドロワーを開くために (これは現在、OSMDroid 固有のものになっています)、ドロワーを開くための OnItemGestureListener があります。
class NodeGestureListener implements OnItemGestureListener<NodeOverlayItem> {
@Override
public boolean onItemLongPress(int index, NodeOverlayItem node) {
if(slidingDrawerActions.isOpened() || slidingDrawerActions.isMoving()) {
return false;
}
slidingDrawerActions.animateOpen();
return false;
}
トリッキーな部分は、(スペースを占有する閉じるボタンに触れるのではなく) MapView をクリックして閉じたかったので、SlidingDrawer.OnDrawerOpenListener および OnDrawerCloseListener クラスを割り当てる必要がありました。引き出しが開いているか閉じているかを示すブール値を単純に反転させました。次に、SlidingDrawer リスナーによって設定された isActionDrawerOpen に基づいて、ドロワーが開いている場合にドロワーを閉じる単純な onClickListener を MapView に設定しました。
public void onCreate(final Bundle savedInstanceState) {
...
this.mapView.setOnClickListener(new MapViewClickListener());
...
this.slidingDrawerActions = (SlidingDrawer)findViewById(R.id.slidingDrawerActions);
this.slidingDrawerActions.setOnDrawerOpenListener(new SlidingDrawerOpenListener());
this.slidingDrawerActions.setOnDrawerCloseListener(new SlidingDrawerCloseListener());
...
}
...
private boolean isActionDrawerOpen = false;
class SlidingDrawerOpenListener implements SlidingDrawer.OnDrawerOpenListener {
@Override
public void onDrawerOpened() {
isActionDrawerOpen = true;
}
}
class SlidingDrawerCloseListener implements SlidingDrawer.OnDrawerCloseListener {
@Override
public void onDrawerClosed() {
isActionDrawerOpen = false;
}
}
private boolean skippedMapViewClickListener = false;
class MapViewClickListener implements OnClickListener {
public void onClick(View view) {
if(isActionDrawerOpen) {
if(skippedMapViewClickListener) {
slidingDrawerActions.animateClose();
skippedMapViewClickListener = false;
} else {
skippedMapViewClickListener = true;
}
}
}
}
skippedMapViewClickListener ブール値に注意してください。私が抱えていた問題は、マーカーを長押しすると、SlidingDrawer リスナーの直後に MapView OnClickListener が呼び出されることでした。つまり、長押しは MapView のクリックと見なされ、さらに長押し自体が OnClickListener が呼び出される前にドロワーを開くため、OnClickListener は常にドロワーが開いていると見なし、それを閉じます。私がしたことは、この方法で最初の onClick を効果的にスキップすることでした。そのため、MapView をクリックするまでドロワーは開いたままになります。うまくいくようです。
これが誰かに役立つことを願っています。このアプローチで解決した問題は 4 つほどあります。