【问题标题】:android - json generated listview onClick only shows last itemandroid - json 生成的 listview onClick 只显示最后一项
【发布时间】:2017-10-11 22:56:35
【问题描述】:

我有一张地图,它显示来自网络的 json 文件中的标记。 我从同一个文件中创建了一个搜索列表视图。 我想要做的是单击任何结果地图缩放与该结果关联的标记后。 但是现在当我点击任何结果时,它只会放大一个标记,这是我的 json 文件中的最后一项。

这是我的代码:

    public class MapAcWithMarker extends FragmentActivity
            implements OnMapReadyCallback {

        static final LatLng TEHRAN = new LatLng(35.697291, 51.392378);
        private GoogleMap mMap;
        public ArrayList<Locations> locationsList;
        public ListView listView;
        private View parentView;
        public DataAdapter adapter;
        ArrayList<Locations> arrayListTemp=new ArrayList<>();
        EditText inputSearch;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main_recyc);
            // Obtain the SupportMapFragment and get notified when the map is ready to be used.
            final SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.map);
            mapFragment.getMapAsync(this);
            //  AsyncTaskGetMarker asyncTaskGetMareker= new AsyncTaskGetMarker();
            new AsyncTaskGetMarker().execute();

            locationsList = new ArrayList<>();
            parentView = findViewById(R.id.parentLayout);
            inputSearch = (EditText) findViewById(R.id.inputSearch);
            listView = (ListView) findViewById(R.id.listView);
            listView.setVisibility(View.INVISIBLE);


            inputSearch.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
                    if(keyCode== KeyEvent.KEYCODE_DEL){
                        listView.setVisibility(View.GONE);
                    }


                    return true;
                }
            });

            inputSearch.addTextChangedListener(new TextWatcher() {

                @Override
                public void onTextChanged(CharSequence cs, int arg1, int arg2, int count) {

                    listView.setVisibility(View.VISIBLE);

                    if(count==0){
                        listView.setVisibility(View.INVISIBLE);

                    }
                    String searchString= inputSearch.getText()
                            .toString().toLowerCase(Locale.getDefault());
                    int realText= searchString.length();
                    arrayListTemp.clear();
                    for (int i =0 ; i <locationsList.size(); i++){
                        try {
                            String pname= locationsList.get(i).getPname()
                                    .toString();

                            String bicycleno= locationsList.get(i).getBicycleno()
                                    .toString();

                            if(realText<=pname.length() && realText<= bicycleno.length())

                                if (searchString.equalsIgnoreCase(pname.substring(0,
                                        realText)) ||
                                        searchString.equalsIgnoreCase(bicycleno.substring(0, realText))

                                        ) {

                                    arrayListTemp.add(locationsList.get(i));

                                } else {
                                    adapter.notifyDataSetChanged();
                                }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
 Log.d("@w2w2w2w","arrayListTemp size is "+arrayListTemp.size());
  adapter = new DataAdapter(MapAcWithMarker.this, arrayListTemp);
  listView.setAdapter(adapter);
                }

                @Override
                public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                                              int arg3) {
                }



                @Override
                public void afterTextChanged(Editable arg0) {


                }
            });
            RequestInterface api = JsonClient.getApiService();

            /**
             * Calling JSON
             */
            Call<StopList> call = api.getJSON();

            /**
             * Enqueue Callback will be call when get response...
             */
            call.enqueue(new Callback<StopList>() {
                @Override
                public void onResponse(Call<StopList> call, Response<StopList> response) {
                    //Dismiss Dialog
                    //  dialog.dismiss();

                    if (response.isSuccessful()) {
                        /**
                         * Got Successfully
                         */
                        locationsList = response.body().getLocations();

                        /**
                         * Binding that List to Adapter
                         */
                        adapter = new DataAdapter(MapAcWithMarker.this,
                                locationsList);
                        listView.setAdapter(adapter);

                    } else {
                        Toast.makeText(getApplicationContext(), "wrong", Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void onFailure(Call<StopList> call, Throwable t) {
                    Toast.makeText(getApplicationContext(), "wrong", Toast.LENGTH_SHORT).show();
                }
            });

        }




        @Override
        public void onMapReady(GoogleMap googleMap) {
            mMap = googleMap;
            mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(TEHRAN, 10));

            new AsyncTaskGetMarker().execute();
        }




        class AsyncTaskGetMarker extends
                AsyncTask<String, String, JSONArray> {

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
            }

            @Override
            protected JSONArray doInBackground(String... params) {

                String json = null;
                JSONArray jsonarray = null;
                HttpURLConnection conn = null;
                BufferedReader reader = null;
                try {

                    URL url = new URL("https://api.myjson.com/bins/1879ab.json");
                    conn = (HttpsURLConnection) url.openConnection();
                    conn.connect();
                    InputStream in = new BufferedInputStream(conn.getInputStream());
                    reader = new BufferedReader
                            (new InputStreamReader(in));

                    StringBuilder builder = new StringBuilder();
                    String line = null;
                    while((line = reader.readLine()) != null) {
                        builder.append(line);
                    }
                    reader.close();
                    String response = builder.toString();
                    JSONObject jsonObject = new JSONObject(response);
                    jsonarray = jsonObject.getJSONArray("stops");
                    // jsonarray = new JSONArray(response);

                } catch (IOException e) {
                    e.printStackTrace();
                } catch (JSONException e) {
                    e.printStackTrace();
                }

                return jsonarray;
            }


           protected void onPostExecute(final JSONArray jsonarray) {
            try {
                final SparseArray<LatLng> positions =
                        new SparseArray<>();
                mMap.clear();
                for (int i = 0; i < jsonarray.length(); i++) {
                    JSONObject obj = jsonarray.getJSONObject(i);

                    String name = obj.getString("name");
                    String pname = obj.getString("pname");
                    String bicycleno = obj.getString("bicycleno");

                    Double lat = obj.getDouble("lat");
                    Double lang = obj.getDouble("lang");
                    final LatLng position = new LatLng(lat, lang);

                    String title = "name: " + name;
                    mMap.addMarker(new MarkerOptions()
                            .position(position).title(title));

                    positions.put(i, position);

}
                    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                            if (positions.get(position) != null)
                                mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(positions.get(position), 15));

                        }
                    });


            } catch (JSONException e) {
                e.printStackTrace();
            }
            }



        }

    }

【问题讨论】:

    标签: android json google-maps listview onclick


    【解决方案1】:

    onPostExecute 内你有:

    position = new LatLng(lat, lang);
    String title = "name: " + name;
    
    mMap.addMarker(new MarkerOptions()
                            .position(position).title(title));
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                            mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(position,15));
                        }
                    });
    

    所以在position 下,你总是最后调用位置。每个onClick 集合都使用此变量(行内:newLatLngZoom(position,15)

    为了解决这个问题,仅在本地方法内部创建 position,您不要在文件顶部声明t need globalLatLng 位置`变量

    final LatLng position = new LatLng(lat, lang);
    //rest of code as above
    

    编辑:还有这些

    lat = obj.getDouble("lat");
    lang = obj.getDouble("lang");
    

    仅在 foronPostExecute 的一个循环内将它们保持在本地

    Double lat = obj.getDouble("lat");
    Double lang = obj.getDouble("lang");
    

    您应该在 MapAcWithMarker 类中删除这些声明(在顶部)

    //below to remove
    public Double lat;
    public Double lang;
    public LatLng position;
    //these are not used anywhere
    public int selectionId= -1;
    Marker markers;
    

    下一次编辑:

    postExecute 方法的完整代码

    protected void onPostExecute(final JSONArray jsonarray) {
        try{
            final SparseArray<LatLng> positions = new SparseArray<>();
            mMap.clear();
            for (int i = 0; i < jsonarray.length(); i++) {
                JSONObject obj = jsonarray.getJSONObject(i);
    
                String name = obj.getString("name");
                String pname = obj.getString("pname");
                String bicycleno = obj.getString("bicycleno");
    
                Double lat = obj.getDouble("lat");
                Double lang = obj.getDouble("lang");
    
                final LatLng position = new LatLng(lat, lang);
                String title = "name: " + name;
    
                mMap.addMarker(new MarkerOptions()
                        .position(position).title(title));
    
                positions.put(i, position);
            }
    
            // set once, outside for loop
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                    if(positions.get(position)!=null)
                        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(positions.get(position),15));
                }
            });
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    

    我已经更仔细地检查了您的代码,但……一团糟。您没有通知适配器有关新数据/json 的信息(即使适配器中的数据与位置、标题等上的解析 json 匹配,您也应该刷新布局)。从 JSON 解析的每个对象也被添加到映射为 MarkermMap.addMarker(...) 方法,但我没有看到任何 mMap.clear(); 方法被调用,所以当再次下载 JSON 时,点可能会重复(在上面添加了这一行)

    另一个编辑 - 你只在列表中绘制了一个项目,因为你有 onTextChanged 方法

    for (int i =0 ; i <locationsList.size(); i++){
        ...
        adapter = new DataAdapter(MapAcWithMarker.this, arrayListTemp);
        listView.setAdapter(adapter);
        ...
    }
    

    适配器的创建应该在for 循环之外完成一次。在循环之后但在启动之前检查 arrayListTemp 有更多项目

    for (int i =0 ; i <locationsList.size(); i++){
        ...
    }
    
    Log.d("@w2w2w2w","arrayListTemp size is "+arrayListTemp.size());
    adapter = new DataAdapter(MapAcWithMarker.this, arrayListTemp);
    listView.setAdapter(adapter);
    

    很多错误...

    【讨论】:

    • 我将 final LatLng position = new LatLng(lat, lang); 放在 onPostExecute 方法中。但它没有用
    • 使用当前代码编辑您的问题,我们将看到接下来的内容:)
    • lat = obj.getDouble("lat");lang = obj.getDouble("lang"); 仍然是全局声明的,最后的值存储在本地创建的所有不同的 LatLng position 中。两行都应该有Double“前缀”,只能是“本地”
    • 我删除了全局值并在方法中声明了Double
    • 查看我上次的编辑,您认为代码中还有更多工作要做......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-31
    • 1970-01-01
    • 2019-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多