2015-12-02 42 views
1

我对Android非常陌生,而且我有一个问题,我不知道从哪里开始寻找其原因。Android ListView充了两次

我有一个片段ListView填充装载器。 当我启动应用程序的ListView显示两次,一个在另一个之上,这里是它的外观像一个截图:

Duplicated list view

我不知道从哪里开始寻找为什么出现这种情况,但我想我将不得不因此这里给出一些代码是我的片段代码:

public class ForecastFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { 

    private static final int FORECAST_LOADER = 0; 
    // For the forecast view we're showing only a small subset of the stored data. 
    // Specify the columns we need. 
    private static final String[] FORECAST_COLUMNS = { 
      // In this case the id needs to be fully qualified with a table name, since 
      // the content provider joins the location & weather tables in the background 
      // (both have an _id column) 
      // On the one hand, that's annoying. On the other, you can search the weather table 
      // using the location set by the user, which is only in the Location table. 
      // So the convenience is worth it. 
      WeatherContract.WeatherEntry.TABLE_NAME + "." + WeatherContract.WeatherEntry._ID, 
      WeatherContract.WeatherEntry.COLUMN_DATE, 
      WeatherContract.WeatherEntry.COLUMN_SHORT_DESC, 
      WeatherContract.WeatherEntry.COLUMN_MAX_TEMP, 
      WeatherContract.WeatherEntry.COLUMN_MIN_TEMP, 
      WeatherContract.LocationEntry.COLUMN_LOCATION_SETTING, 
      WeatherContract.WeatherEntry.COLUMN_WEATHER_ID, 
      WeatherContract.LocationEntry.COLUMN_COORD_LAT, 
      WeatherContract.LocationEntry.COLUMN_COORD_LONG 
    }; 

    // These indices are tied to FORECAST_COLUMNS. If FORECAST_COLUMNS changes, these 
    // must change. 
    static final int COL_WEATHER_ID = 0; 
    static final int COL_WEATHER_DATE = 1; 
    static final int COL_WEATHER_DESC = 2; 
    static final int COL_WEATHER_MAX_TEMP = 3; 
    static final int COL_WEATHER_MIN_TEMP = 4; 
    static final int COL_LOCATION_SETTING = 5; 
    static final int COL_WEATHER_CONDITION_ID = 6; 
    static final int COL_COORD_LAT = 7; 
    static final int COL_COORD_LONG = 8; 

    private ForecastAdapter mForecastAdapter; 

    public ForecastFragment() { 
    } 

    @Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
     super.onCreateOptionsMenu(menu, inflater); 
     inflater.inflate(R.menu.menu_main, menu); 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 

     //noinspection SimplifiableIfStatement 
     if (id == R.id.action_settings) { 
      startActivity(new Intent(getActivity(), SettingsActivity.class)); 
      return true; 
     } 

     return super.onOptionsItemSelected(item); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     // The CursorAdapter will take data from our cursor and populate the ListView. 
     mForecastAdapter = new ForecastAdapter(getActivity(), null, 0); 

     View rootView = inflater.inflate(R.layout.fragment_main, container, false); 

     ListView listView = (ListView)rootView.findViewById(R.id.listview_forecast); 
     listView.setAdapter(mForecastAdapter); 

     listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 

      @Override 
      public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { 
       // CursorAdapter returns a cursor at the correct position for getItem(), or null 
       // if it cannot seek to that position 
       Cursor cursor = (Cursor) adapterView.getItemAtPosition(position); 
       if (cursor != null) { 
        String locationSetting = Utility.getPreferredLocation(getActivity()); 
        Intent detailIntent = new Intent(getActivity(), DetailActivity.class) 
          .setData(WeatherContract.WeatherEntry.buildWeatherLocationWithDate(
            locationSetting, cursor.getLong(COL_WEATHER_DATE) 
          )); 
        startActivity(detailIntent); 
       } 
      } 
     }); 
     return rootView; 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     getLoaderManager().initLoader(FORECAST_LOADER, null, this); 
     super.onActivityCreated(savedInstanceState); 
    } 

    private void updateWeather(){ 
     FetchWeatherTask weatherTask = new FetchWeatherTask(getActivity()); 
     String location = Utility.getPreferredLocation(getActivity()); 
     weatherTask.execute(location); 
    } 

    void onLocationChanged() { 
     updateWeather(); 
     getLoaderManager().restartLoader(FORECAST_LOADER, null, this); 
    } 

    @Override 
    public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
     String location = Utility.getPreferredLocation(getActivity()); 

     //Sort order: Ascending by date 
     String sortOrder = WeatherContract.WeatherEntry.COLUMN_DATE + " ASC"; 
     Uri weatherForLocation = WeatherContract.WeatherEntry.buildWeatherLocationWithStartDate(
       location, System.currentTimeMillis()); 

     return new CursorLoader(getActivity(), 
       weatherForLocation, 
       FORECAST_COLUMNS, 
       null, 
       null, 
       sortOrder); 
    } 

    @Override 
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 
     if (!data.moveToFirst()) 
      updateWeather(); 
     mForecastAdapter.swapCursor(data); 
    } 

    @Override 
    public void onLoaderReset(Loader<Cursor> loader) { 
     mForecastAdapter.swapCursor(null); 
    } 
} 
+1

您是否在活动的布局中声明了碎片,并在同一时间将其添加到事务中? – Blackbelt

+0

对不起我的无知,但你能告诉我你是什么意思?我在这段代码的'onCreateView'方法中查看rootView = inflater.inflate(R.layout.fragment_main,container,false);'content_main.xml'文件中:''那是什么意思? –

+0

你可以发布你的Activity的onCreate和它的布局吗? – Blackbelt

回答

2

从我所看到的截图,它看起来像你添加了相同的片段两次,当前视图的层次结构。最常见的错误是在Activity的布局中声明片段,使用<fragment标记并以编程方式使用特定事务,这当然会导致屏幕上出现两次相同的片断。要修复它,请将布局中的<fragment替换为<FrameLayout,然后以编程方式添加片段。例如。

<FrameLayout 
    android:id="@+id/container" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" /> 

,并在活动的onCreate

if (savedInstanceState == null){ 
    getSupportFragmentManager() .beginTransaction() .add(R.id.container, new ForecastFragment(), FORECASTFRAGMENT_TAG) .commit(); 
} 
+0

请问一个问题,我从xml布局文件中删除了这个'tools:layout =“@ layout/fragment_main”',但它没有帮助,只是当我删除这个'getSupportFragmentManager().beginTransaction().add(R。 id.container,新的F​​orecastFragment(),FORECASTFRAGMENT_TAG).commit();'它有帮助,我想不得不像这样使用'getSupportFragmentManager().beginTransaction().add(R.id。容器,新的ForecastFragment(),FORECASTFRAGMENT_TAG).commit();'不在xml中。那么,我该如何做到这一点? –

+0

您必须从xml中删除整个' Blackbelt

+0

这是“content_main.xml”文件的内容:'如果我将它全部删除它会给出一个错误,因为该文件是空的... –

0

正在发生的事情是,你是通过XML声明的片段,然后再充气它

您应该使用更好的方法,而不是将片段放入XML中,添加一个空的framelayout并每次添加/替换片段(看看我在自定义库中的this方法),这样它只会显示一次, 或不再膨胀它(但onResume也可以复制它,并且不提供更改显示片段的自由)。

+0

非常感谢您的回答,这也是正确的 –