1. 程式人生 > >4.21WorldWindAndroid空間要素的屬性查詢

4.21WorldWindAndroid空間要素的屬性查詢

問題描述:如何通過點選地圖上的要素彈出相應的屬性顯示框呢?

問題分析:這裡其實涉及到三個問題,第一個問題是如何選中地圖上的要素,第二個問題是如何獲得要素的屬性,第三個問題是如何涉及彈框顯示!

第一個問題,顯然需要有一個方法能夠根據螢幕點選的位置獲取到對應的要素,這個方法在WorldWindAndroid中就是

 PickedObjectList pickList = getWorldWindow().pick(event.getX(), event.getY());

此外,我們希望在要素被選中時高亮顯示,這一點如何實現呢?

在WorldWindAndroid中的要素類都繼承了Highlightable這個類,只有兩個方法,isHighlighted獲取高亮顯示的狀態,setHighlighted設定高亮顯示的狀態,關鍵還不在這裡,關鍵在要素類是如何利用對高亮狀態的判斷來顯示不同的效果的呢?

public abstract class AbstractShape extends AbstractRenderable implements Attributable, Highlightable {

    protected ShapeAttributes attributes;

    protected ShapeAttributes highlightAttributes;

    protected ShapeAttributes activeAttributes;

    protected boolean highlighted;

為什麼一個要素,要設定這麼多屬性呢?

attributes是正常顯示的屬性,而highlightAttributes顧名思義就是高亮顯示的屬性了,而activeAttributes就是根據顯示狀態來決定是取attributes呢還是取highlightAttributes,然後通過activeAttributes的設定來繪製要素啦!

    @Override
    protected void doRender(RenderContext rc) {
        // Don't render anything if the shape is not visible.
        if (!this.intersectsFrustum(rc)) {
            return;
        }

        // Select the currently active attributes. Don't render anything if the attributes are unspecified.
        this.determineActiveAttributes(rc);
if (this.activeAttributes == null) { return; }
    protected void determineActiveAttributes(RenderContext rc) {
        if (this.highlighted && this.highlightAttributes != null) {
            this.activeAttributes = this.highlightAttributes;
        } else {
            this.activeAttributes = this.attributes;
        }
    }

程式碼已經寫得很清楚了,所以,如果希望要素被選中能夠高亮顯示,一定要在建立要素的時候設定上相應的高亮屬性!

第二個問題,如果需要實現這一目標,關鍵在於獲取的要素物件與相應屬性的關聯問題,如果,該要素只是一個圖形物件,而不包含任何與屬性進行關聯的資訊,那麼是無法實現屬性查詢,而要實現關聯的方法有兩種,一種是建立唯一索引,通過索引查詢屬性資料庫,另一種就是在該要素類中直接定義儲存屬性資料的變數,這樣獲取要素的同時就直接可以得到相應的屬性了,顯然第二種方式更為方便,而WorldWindAndroid也充分考慮到了這一點,Path,Polygon都繼承自AbstractShape,AbstractShape,AbstractShape繼承了AbstractRenderable,Placemark則直接繼承了AbstractRenderable,最關鍵的地方來了,AbstractRenderable裡面有兩個重要屬性,一個是要素的顯示名稱displayName,一個是使用者定製屬性uesrProperties

public abstract class AbstractRenderable implements Renderable {

    protected String displayName;

    protected boolean enabled = true;

    protected Object pickDelegate;

    protected Map<Object, Object> userProperties;

所以,我們在建立要素的時候,只需要將要素的屬性直接寫入這兩個屬性中,就可以在選中要素的時候獲取到要素的屬性資訊了!

當然,如果WorldWind的其他版本中沒有這麼設計,我們可以繼承相應的要素類按照這樣的思路進行拓展即可!

第三個問題,彈框的顯示,這個就比較輕鬆了,直接使用Android的AlertDialog就可以實現了,就不囉嗦了!


測試用例:

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.RadioButton;
import android.widget.TableLayout;
import android.widget.Toast;
import com.R;
import java.util.ArrayList;
import gov.nasa.worldwind.PickedObject;
import gov.nasa.worldwind.PickedObjectList;
import gov.nasa.worldwind.WorldWindow;
import gov.nasa.worldwind.geom.Offset;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.globe.BasicElevationCoverage;
import gov.nasa.worldwind.layer.BackgroundLayer;
import gov.nasa.worldwind.layer.BlueMarbleLandsatLayer;
import gov.nasa.worldwind.layer.RenderableLayer;
import gov.nasa.worldwind.render.Color;
import gov.nasa.worldwind.render.ImageSource;
import gov.nasa.worldwind.shape.Path;
import gov.nasa.worldwind.shape.Placemark;
import gov.nasa.worldwind.shape.PlacemarkAttributes;
import gov.nasa.worldwind.shape.Polygon;
import gov.nasa.worldwind.shape.ShapeAttributes;
import gov.nasa.worldwind.shape.TextAttributes;

/**
 * Creates a simple view of a globe with touch navigation and a few layers.
 */
public class BasicGlobeActivity extends AppCompatActivity implements GestureDetector.OnGestureListener{

    /**
     * This protected member allows derived classes to override the resource used in setContentView.
     */
    protected int layoutResourceId = R.layout.activity_globe;
    //check to draw or not
    CheckBox checkDraw ;
    //check graphics type
    RadioButton checkPoint,checkPolyline,checkPolygon;
    //gesture detector
    GestureDetectorCompat detectorCompat ;
    //basic support
    RenderableLayer labelsLayer = new RenderableLayer();
    ArrayList<Position> pos = new ArrayList<>();
    Position currentPosition;
    boolean startDraw =false;
    //PlacemarkLayer
    RenderableLayer placemarkLayer = new RenderableLayer();
   //Polyline
    RenderableLayer temPolylineLayer = new RenderableLayer();
    RenderableLayer polylineLayer = new RenderableLayer();

    // Polygon
    RenderableLayer temPolygonLayer = new RenderableLayer();
    RenderableLayer polygonLayer = new RenderableLayer();


    /**
     * The WorldWindow (GLSurfaceView) maintained by this activity
     */
    protected WorldWindow wwd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Establish the activity content
        setContentView(this.layoutResourceId);
        detectorCompat = new GestureDetectorCompat(this,this);
        checkDraw = (CheckBox)findViewById(R.id.checkDraw);
        checkPoint = (RadioButton)findViewById(R.id.point);
        checkPolyline = (RadioButton)findViewById(R.id.polyline);
        checkPolygon = (RadioButton)findViewById(R.id.polygon);
        checkDraw.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked) {
                    wwd.setLongClickable(true);
                    wwd.setOnTouchListener(new View.OnTouchListener() {
                        @Override
                        public boolean onTouch(View v, MotionEvent event) {
                            return detectorCompat.onTouchEvent(event);
                        }
                    });
                }else{
                    wwd.setLongClickable(false);
                    wwd.setOnTouchListener(null);
                }
            }
        });

        // Create the World Window (a GLSurfaceView) which displays the globe.
        this.wwd = new WorldWindow(this);
        // Override the World Window's built-in navigatior behavior by adding picking support.
        this.wwd.setWorldWindowController(new PickObjectController(this));
        // Add the WorldWindow view object to the layout that was reserved for the globe.
        FrameLayout globeLayout = (FrameLayout) findViewById(R.id.globe);
        globeLayout.addView(this.wwd);

        // Setup the World Window's layers.
        this.wwd.getLayers().addLayer(new BackgroundLayer());
        this.wwd.getLayers().addLayer(new BlueMarbleLandsatLayer());

        // Setup the World Window's elevation coverages.
        this.wwd.getGlobe().getElevationModel().addCoverage(new BasicElevationCoverage());
        this.wwd.getLayers().addLayer(placemarkLayer);
        this.wwd.getLayers().addLayer(temPolylineLayer);
        this.wwd.getLayers().addLayer(polylineLayer);
        this.wwd.getLayers().addLayer(temPolygonLayer);
        this.wwd.getLayers().addLayer(polygonLayer);
        this.wwd.getLayers().addLayer(labelsLayer);

    }

    @Override
    protected void onPause() {
        super.onPause();
        this.wwd.onPause(); // pauses the rendering thread
    }

    @Override
    protected void onResume() {
        super.onResume();
        this.wwd.onResume(); // resumes a paused rendering thread
    }



    public WorldWindow getWorldWindow() {
        return this.wwd;
    }

    @Override
    public boolean onDown(MotionEvent e) {

        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        //清空之前的點資料
            if(!startDraw) {
                pos.clear();
                startDraw = true;
            }
            if (checkPoint.isChecked()) {
                currentPosition = this.getCurrentPosition(e);
                inputPointAttriDialog();
            } else if (checkPolyline.isChecked()) {
                currentPosition = this.getCurrentPosition(e);
                pos.add(currentPosition);
                if (pos.size() > 1) {
                    ShapeAttributes shapeAttributes = new ShapeAttributes();
                    shapeAttributes.setDrawVerticals(true); // display the extruded verticals
                    shapeAttributes.setInteriorColor(new Color(1, 1, 1, 0.5f)); // 50% transparent white
                    shapeAttributes.setOutlineWidth(3);
                    temPolylineLayer.clearRenderables();
                    temPolylineLayer.addRenderable(new Path(pos, shapeAttributes));
                    wwd.requestRedraw();
                }
            } else if (checkPolygon.isChecked()) {
                currentPosition = this.getCurrentPosition(e);
                pos.add(currentPosition);
                if (pos.size() > 2) {
                    ShapeAttributes shapeAttributes = new ShapeAttributes();
                    shapeAttributes.setDrawVerticals(true); // display the extruded verticals
                    shapeAttributes.setInteriorColor(new Color(1, 1, 1, 0.5f)); // 50% transparent white
                    shapeAttributes.setOutlineWidth(3);
                    temPolygonLayer.clearRenderables();
                    temPolygonLayer.addRenderable(new Polygon(pos, shapeAttributes));
                    wwd.requestRedraw();
                }
            }

        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {

            if(checkPolyline.isChecked()){
                currentPosition = this.getCurrentPosition(e);
                pos.add(currentPosition);
                inputPolylineAttriDialog();
                //clear temp layer:清空臨時圖層
                temPolylineLayer.clearRenderables();
            }else if(checkPolygon.isChecked()){
                currentPosition = this.getCurrentPosition(e);
                pos.add(currentPosition);
                inputPolygonAttriDialog();
                //clear temp layer:清空臨時圖層
                temPolygonLayer.clearRenderables();
            }
        //本圖形繪製結束,準備繪製新圖形
          startDraw = false;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        return false;
    }
    public Position getCurrentPosition(MotionEvent event) {
        // Forget our last picked object
        // Perform a new pick at the screen x, y
        PickedObjectList pickList = getWorldWindow().pick(event.getX(), event.getY());

        // Get the top-most object for our new picked object
        PickedObject top = pickList.topPickedObject();
        Position p = null;
        if (top != null) {
            if (top != null&&top.isTerrain()) {
                p = top.getTerrainPosition();
            }
        }
        return p;
    }





    public void inputPointAttriDialog(){

        TableLayout attributeFrom = (TableLayout)getLayoutInflater().inflate(R.layout.feature_attribute,null);
        final EditText name = (EditText)attributeFrom.findViewById(R.id.featureName);
        final EditText type = (EditText)attributeFrom.findViewById(R.id.featureType);
        final EditText desc = (EditText)attributeFrom.findViewById(R.id.featureDesc);
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("設定Point屬性")
                .setView(attributeFrom)
                .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                        Toast.makeText(getApplicationContext(),"單擊了[確定]按鈕",Toast.LENGTH_SHORT).show();
                        //空間及屬性資料存入資料庫
                        //繪製placemark
                        ShapeAttributes shapeAttributes = new ShapeAttributes();
                        shapeAttributes.setDrawVerticals(true); // display the extruded verticals
                        shapeAttributes.setOutlineColor(new Color(1,0,0,1));
                        shapeAttributes.setInteriorColor(new Color(1, 0, 0, 0.5f)); // 50% transparent white
                        shapeAttributes.setOutlineWidth(20);

                        TextAttributes attrs = new TextAttributes();
                        attrs.setTextColor(new Color(0, 1, 0, 1)); // green via r,g,b,a
                        attrs.setTextOffset(Offset.bottomCenter());
                        attrs.setTypeface(Typeface.DEFAULT); // system default bold typeface
                        //attrs.setTextSize(30);
                        Placemark placemark = createPlacemark(currentPosition,name.getText().toString());
                        placemark.setDisplayName(name.getText().toString());
                        placemark.putUserProperty("name",name.getText().toString());
                        placemark.putUserProperty("type",type.getText().toString());
                        placemark.putUserProperty("desc",desc.getText().toString());
                        placemarkLayer.addRenderable(placemark);
                        //繪製labels標識
                       /* TextAttributes attrs = new TextAttributes();
                        attrs.setTextColor(new Color(0, 1, 0, 1)); // green via r,g,b,a
                        attrs.setTextOffset(Offset.bottomCenter());
                        attrs.setTypeface(Typeface.DEFAULT); // system default bold typeface
                        //attrs.setTextSize(30); // 48 screen pixels,強制顯示範圍會在字數不夠的情況下發生字型傾斜和重複
                        labelsLayer.addRenderable(new Label(currentPosition,name.getText().toString(),attrs));*/
                        wwd.requestRedraw();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(getApplicationContext(),"單擊了[取消]按鈕",Toast.LENGTH_SHORT).show();

                    }
                })
                .create()
                .show();
    }


    public void inputPolylineAttriDialog(){

        TableLayout attributeFrom = (TableLayout)getLayoutInflater().inflate(R.layout.feature_attribute,null);
        final EditText name = (EditText)attributeFrom.findViewById(R.id.featureName);
        final EditText type = (EditText)attributeFrom.findViewById(R.id.featureType);
        final EditText desc = (EditText)attributeFrom.findViewById(R.id.featureDesc);
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("設定Polyline屬性")
                .setView(attributeFrom)
                .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                        Toast.makeText(getApplicationContext(),"單擊了[確定]按鈕",Toast.LENGTH_SHORT).show();
                        //空間及屬性資料存入資料庫
                        //繪製polyline
                        Path polyline  = createPolyline(pos);
                        polyline.setDisplayName(name.getText().toString());
                        polyline.putUserProperty("name",name.getText().toString());
                        polyline.putUserProperty("type",type.getText().toString());
                        polyline.putUserProperty("desc",desc.getText().toString());
                        polylineLayer.addRenderable(polyline);

                       /* //繪製labels標識
                        TextAttributes attrs = new TextAttributes();
                        attrs.setTextColor(new Color(0, 1, 0, 1)); // green via r,g,b,a
                        attrs.setTextOffset(Offset.bottomCenter());
                        attrs.setTypeface(Typeface.DEFAULT); // system default bold typeface
                        //attrs.setTextSize(30); // 48 screen pixels
                        labelsLayer.addRenderable(new Label(currentPosition,name.getText().toString(),attrs));*/
                        wwd.requestRedraw();

                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(getApplicationContext(),"單擊了[取消]按鈕",Toast.LENGTH_SHORT).show();
                        wwd.requestRedraw();
                    }
                })
                .create()
                .show();
    }


    public void inputPolygonAttriDialog(){

        TableLayout attributeFrom = (TableLayout)getLayoutInflater().inflate(R.layout.feature_attribute,null);
        final EditText name = (EditText)attributeFrom.findViewById(R.id.featureName);
        final EditText type = (EditText)attributeFrom.findViewById(R.id.featureType);
        final EditText desc = (EditText)attributeFrom.findViewById(R.id.featureDesc);
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("設定Polygon屬性")
                .setView(attributeFrom)
                .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                        Toast.makeText(getApplicationContext(),"單擊了[確定]按鈕",Toast.LENGTH_SHORT).show();
                        //空間及屬性資料存入資料庫
                        //繪製ploygon
                        Polygon polygon  = createPolygon(pos);
                        polygon.setDisplayName(name.getText().toString());
                        polygon.putUserProperty("name",name.getText().toString());
                        polygon.putUserProperty("type",type.getText().toString());
                        polygon.putUserProperty("desc",desc.getText().toString());
                        polygonLayer.addRenderable(polygon);
                       /* //繪製labels標識
                        TextAttributes attrs = new TextAttributes();
                        attrs.setTextColor(new Color(0, 1, 0, 1)); // green via r,g,b,a
                        attrs.setTextOffset(Offset.bottomCenter());
                        attrs.setTypeface(Typeface.DEFAULT); // system default bold typeface
                        //attrs.setTextSize(30); // 48 screen pixels
                        labelsLayer.addRenderable(new Label(currentPosition,name.getText().toString(),attrs));*/
                        wwd.requestRedraw();

                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(getApplicationContext(),"單擊了[取消]按鈕",Toast.LENGTH_SHORT).show();
                        wwd.requestRedraw();
                    }
                })
                .create()
                .show();
    }


    private static Placemark createPlacemark(Position position,String displayName) {
        final double NORMAL_IMAGE_SCALE = 3.0;
        final double HIGHLIGHTED_IMAGE_SCALE = 4.0;
        Placemark placemark =new  Placemark(position, PlacemarkAttributes.createWithImage(ImageSource.fromResource(R.drawable.school)),displayName);
        placemark.getAttributes().setImageOffset(Offset.bottomCenter()).setImageScale(NORMAL_IMAGE_SCALE).setDrawLeader(true);
        placemark.setHighlightAttributes(new PlacemarkAttributes(placemark.getAttributes()).setImageScale(HIGHLIGHTED_IMAGE_SCALE));
        return placemark;
    }
    private static Path createPolyline(ArrayList<Position> position) {
       Path polyline = new Path(position);
        ShapeAttributes attributes = new ShapeAttributes();
        attributes.setDrawVerticals(true); // display the extruded verticals
        attributes.setOutlineColor(new Color(1,0,0,1));
        attributes.setInteriorColor(new Color(1, 1, 1, 0.5f)); // 50% transparent white
        attributes.setOutlineWidth(3);
       polyline.setAttributes(attributes);
        ShapeAttributes highlightAttributes = new ShapeAttributes();
        highlightAttributes.setDrawVerticals(true); // display the extruded verticals
        highlightAttributes.setOutlineColor(new Color(0,0,1,1));
        highlightAttributes.setInteriorColor(new Color(1, 1, 1, 0.5f)); // 50% transparent white
        highlightAttributes.setOutlineWidth(6);
       polyline.setHighlightAttributes(highlightAttributes);
        return polyline;
    }

    private static Polygon createPolygon(ArrayList<Position> position) {
        Polygon polygon = new Polygon(position);
        ShapeAttributes attributes = new ShapeAttributes();
        attributes.setDrawVerticals(true); // display the extruded verticals
        attributes.setOutlineColor(new Color(1,0,0,1));
        attributes.setInteriorColor(new Color(1, 1, 1, 0.5f)); // 50% transparent white
        attributes.setOutlineWidth(3);
        polygon.setAttributes(attributes);
        ShapeAttributes highlightAttributes = new ShapeAttributes();
        highlightAttributes.setDrawVerticals(true); // display the extruded verticals
        highlightAttributes.setOutlineColor(new Color(0,0,1,1));
        highlightAttributes.setInteriorColor(new Color(1, 1, 1, 0.5f)); // 50% transparent white
        highlightAttributes.setOutlineWidth(6);
        polygon.setHighlightAttributes(highlightAttributes);
        return polygon;
    }

}
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import com.R;
import java.util.ArrayList;
import gov.nasa.worldwind.BasicWorldWindowController;
import gov.nasa.worldwind.PickedObject;
import gov.nasa.worldwind.PickedObjectList;
import gov.nasa.worldwind.shape.Highlightable;
import gov.nasa.worldwind.shape.Path;
import gov.nasa.worldwind.shape.Placemark;
import gov.nasa.worldwind.shape.Polygon;

/**
 * Created by Lenovo on 2018/4/21.
 */

public class PickObjectController extends BasicWorldWindowController {

    protected Object pickedObject;          // last picked object from onDown events

    protected Object selectedObject;        // last "selected" object from single tap
    protected Context context;

    public PickObjectController(Context context) {
        this.context = context;
    }

    /**
     * Assign a subclassed SimpleOnGestureListener to a GestureDetector to handle the "pick" events.
     */
    protected GestureDetector pickGestureDetector = new GestureDetector(
            context, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onDown(MotionEvent event) {
            pick(event);    // Pick the object(s) at the tap location
            return false;   // By not consuming this event, we allow it to pass on to the navigation gesture handlers
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            toggleSelection();  // Highlight the picked object
            // By not consuming this event, we allow the "up" event to pass on to the navigation gestures,
            // which is required for proper zoom gestures.  Consuming this event will cause the first zoom
            // gesture to be ignored.  As an alternative, you can implement onSingleTapConfirmed and consume
            // event as you would expect, with the trade-off being a slight delay tap response.
            return false;
        }
    });

    /**
     * Delegates events to the pick handler or the native World Wind navigation handlers.
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Allow pick listener to process the event first.
        boolean consumed = this.pickGestureDetector.onTouchEvent(event);

        // If event was not consumed by the pick operation, pass it on the globe navigation handlers
        if (!consumed) {

            // The super class performs the pan, tilt, rotate and zoom
            return super.onTouchEvent(event);
        }
        return consumed;
    }

    /**
     * Performs a pick at the tap location.
     */
    public void pick(MotionEvent event) {
        // Forget our last picked object
        this.pickedObject = null;

        // Perform a new pick at the screen x, y
        PickedObjectList pickList = getWorldWindow().pick(event.getX(), event.getY());

        // Get the top-most object for our new picked object
        PickedObject topPickedObject = pickList.topPickedObject();
        if (topPickedObject != null) {
            this.pickedObject = topPickedObject.getUserObject();
        }
    }

    /**
     * Toggles the selected state of a picked object.
     */
    public void toggleSelection() {

        // Display the highlight or normal attributes to indicate the
        // selected or unselected state respectively.
        if (pickedObject instanceof Highlightable) {

            // Determine if we've picked a "new" object so we know to deselect the previous selection
            boolean isNewSelection = pickedObject != this.selectedObject;

            // Only one object can be selected at time, deselect any previously selected object
            if (isNewSelection && this.selectedObject instanceof Highlightable) {
                ((Highlightable) this.selectedObject).setHighlighted(false);
            }

            // Show the selection by showing its highlight attributes
            ((Highlightable) pickedObject).setHighlighted(isNewSelection);
            this.getWorldWindow().requestRedraw();

            // Track the selected object
            this.selectedObject = isNewSelection ? pickedObject : null;

            showAttributeDialog();//show attribute if selectObject not null
        }
    }

    public void showAttributeDialog(){
        //關鍵問題是如何從pickobject中得到我們設定的要素屬性資料呢?
       final ArrayList<String> items =  new ArrayList<>();
        if(selectedObject!=null){
            if(selectedObject instanceof Placemark){
                Placemark selectedPlacemark = (Placemark)selectedObject;
                String name = selectedPlacemark.getUserProperty("name").toString();
                String type = selectedPlacemark.getUserProperty("type").toString();
                String desc = selectedPlacemark.getUserProperty("desc").toString();
                items.add("名稱:"+name);
                items.add("型別:"+type);
                items.add("描述:"+desc);
            }else if(selectedObject instanceof Path){
                Path selectedPolyline = (Path) selectedObject;
                String name = selectedPolyline.getUserProperty("name").toString();
                String type = selectedPolyline.getUserProperty("type").toString();
                String desc = selectedPolyline.getUserProperty("desc").toString();
                items.add("名稱:"+name);
                items.add("型別:"+type);
                items.add("描述:"+desc);
            }else if(selectedObject instanceof Polygon){
                Polygon selectedPolygon = (Polygon)selectedObject;
                String name = selectedPolygon.getUserProperty("name").toString();
                String type = selectedPolygon.getUserProperty("type").toString();
                String desc = selectedPolygon.getUserProperty("desc").toString();
                items.add("名稱:"+name);
                items.add("型別:"+type);
                items.add("描述:"+desc);
            }

            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setTitle("要素屬性資訊")
                    .setAdapter(new ArrayAdapter<String>(context, R.layout.array_item, items), new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(context,"你選中了《"+items.get(which)+"》",Toast.LENGTH_SHORT).show();
                        }
                    })
                    .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(context,"單擊了[確定]按鈕",Toast.LENGTH_SHORT).show();
                        }
                    })
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Toast.makeText(context,"單擊了[取消]按鈕",Toast.LENGTH_SHORT).show();
                        }
                    })
                    .create()
                    .show();
        }

    }
}

專案地址:

https://gitee.com/lq_project/CampusProjectRepository/tree/master/CampusProject/test/src/main/java/com/worldwind/test