0

私は運がなければ、さまざまな角度からこれにアプローチしようとしました。たぶん、一般的な質問をすることが助けになるでしょう。

技術的には、Google の Maps API ではなく、osmdroid の MapView 実装を使用していますが、この質問は、onCreate で定義された main_activity.xml に対するより一般的なプログラムによるビューだと思います。

基本的に MainActivity で、MapView などのビューを作成し、プログラムで ContentView として設定すると、アプリに表示する他のビューもプログラムで追加する必要があります。

public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.mapView = new MapView(this, 256);
    ...
    this.setContentView(this.mapView);
}

ContentView を activity_main として設定しようとすると、MapView を onCreate で調整できません。たぶん何かが足りない: (カスタム オフライン タイル セットの読み込みを処理し、マップ上にマーカーを配置するメソッドがあることに注意してください...)

public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    this.mapView = (MapView)findViewById(R.id.mapview);
    ...
    this.intializeMapTiles();
    this.mapView.setBuiltInZoomControls(true);
    this.mapView.setMultiTouchControls(true);
    this.mapController.setCenter(new GeoPoint((int)(50.349622 * 1E6), (int)(-71.823700 *1E6)));
    ...
    this.mapView.invalidate();
}

この場合の私の activity_main.xml は次のとおりです。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <org.osmdroid.views.MapView
    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"/>

</RelativeLayout>

ContentView (acitivty_main) から MapView を取得しようとすると、メソッドを変更しても影響はありません。レンダリングされている正確な MapView にアクセスできないかのようです。MapView を無効にしようとしましたが、問題ありません。デフォルトの外観と動作の MapView を取得します。

これを解決しようとしている理由は、当然、アプリに複数の MapView を含めることを探しているからです。SlidingDrawer、またはマップマーカーを長押ししたときにのみ表示されるボタンを使用してビューを表示する方法を含めたいと思います。(マップ マーカーの長押しでトースト ポップアップが表示されることに注意してください。この点に関しては良好です)

これらの他のビュー (SlideingDrawer など) は、main_activity.xml からではなく、プログラムで追加する必要があります。それにも catch-22 があり、SlidingDrawer コンストラクターが xml からの AttributeSet を必要とするため、自分で作成するのは困難です。(やってみました) では、レイアウトにも気を配る必要があります。

誰にも提案はありますか?一般かそれ以外か?ありがとう!

4

1 に答える 1

1

これは、いくつかの理由で実際に他の人にとって役立つ場合があります。

プログラムコンストラクターを介して必要な方法でのみ構成できるビューを使用する必要がある場合 (たとえば、 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 つほどあります。

于 2012-12-18T05:23:55.963 に答える