接着昨天的任務,咱們今天實現左右滑動能夠切換城市的功能。html
這裏就須要引入新的控件了,Android給咱們提供了ViewPager,咱們就使用這個,同時,顯示天氣的界面咱們也再也不使用Activity,而改成Fragment。android
Fragment能夠認爲是可複用的UI組件,有本身的佈局和完整的生命週期,能夠處理自己的事件,可是必須依存於Activity,不能脫離Activity而存在。數據庫
能夠看出來,Fragment的生命週期跟Activity很是類似,而且會隨着Activity的銷燬而銷燬。json
下面,咱們來戰。api
首先,新建一個Fragment的子類,取名爲WeatherFragment。ide
public class WeatherFragment extends Fragment { @Override public void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); } @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) { return super.onCreateView( inflater, container, savedInstanceState ); } }
這是用來顯示天氣的界面,而咱們以前是直接在Activity中顯示的,須要把這部分代碼給移植到Fragment中。佈局
這是個麻煩的過程,不過沒關係,慢慢來。post
新建一個Layout,取名爲frag_weather.xml,而後把activity_main.xml中的代碼給複製過來,this
<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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" > <ListView android:id="@+id/weather_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" > </ListView> </RelativeLayout>
咱們讓WeatherFragment使用新的Layout,再把MainActivity中關於天氣的代碼移植到WeatherFragment中,url
public class WeatherFragment extends Fragment { @ViewInject( R.id.weather_list ) private ListView lstWeather; private WeatherAdapter adapter; private BaiduData data; private List<WeatherDataBean> datas; private String city; public void setCity( String city ) { this.city = city; } @Override public void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); datas = new ArrayList<WeatherDataBean>(); adapter = new WeatherAdapter( getActivity(), datas ); } @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) { View view = inflater.inflate( R.layout.frag_weather, null ); ViewUtils.inject( this, view ); lstWeather.setAdapter( adapter ); getWeather(); return view; } private void getWeather() { HttpUtils http = new HttpUtils(); RequestParams params = new RequestParams(); params.addQueryStringParameter( "location", city ); params.addQueryStringParameter( "output", "json" ); params.addQueryStringParameter( "ak", "YknGmxIoPugT7YrNrG955YLS" ); http.send( HttpMethod.GET, "http://api.map.baidu.com/telematics/v3/weather", params, new RequestCallBack<String>() { @Override public void onSuccess( ResponseInfo<String> responseInfo ) { String weather = responseInfo.result; Gson gson = new Gson(); data = gson.fromJson( weather, BaiduData.class ); datas.clear(); datas.addAll( data.getResults().get( 0 ).getWeather_data() ); adapter.notifyDataSetChanged(); Log.v( "onSuccess", data.toString() ); } @Override public void onFailure( HttpException arg0, String arg1 ) { Log.v( "onFailure", arg1 ); } } ); } }
而後,修改主頁面activity_main.xml爲:
<?xml version="1.0"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <LinearLayout android:id="@+id/viewGroup" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="30dp" android:gravity="center_horizontal" android:orientation="horizontal" > </LinearLayout> </RelativeLayout>
這裏咱們引入了ViewPager,而且還有一個LinearLayout,其中ViewPager咱們用來顯示天氣,Linearlayout用來做爲指示器,表示咱們當前所選城市的次序。
以後,修改咱們主頁面的代碼,主界面如今的做用主要是兩個:
1. 初次啓動的時候,獲取所在地城市
2. 處理切換Fragment的邏輯
3. 處理頁面跳轉/返回的邏輯
public class MainActivity extends FragmentActivity { @ViewInject( R.id.viewPager ) private ViewPager pager; @ViewInject( R.id.viewGroup ) private LinearLayout layout; private MyAdapter mAdapter; private List<SelectCityBean> citys; private LocationClient mLocationClient; private BDLocationListener myListener; private List<ImageView> imageViews; @Override protected void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); setContentView( R.layout.activity_main ); Log.v( "WeatherAPP", "onCreate" ); ViewUtils.inject( this ); imageViews = new ArrayList<ImageView>(); citys = readCity(); mAdapter = new MyAdapter( getSupportFragmentManager() ); pager.setAdapter( mAdapter ); pager.setOnPageChangeListener( new OnPageChangeListener() { @Override public void onPageSelected( int arg0 ) { setTitle( citys.get( arg0 ).getCityName() + "天氣" ); setImageBackground( arg0 ); } @Override public void onPageScrolled( int arg0, float arg1, int arg2 ) { } @Override public void onPageScrollStateChanged( int arg0 ) { } } ); if( citys == null || citys.size() == 0 ) { citys = new ArrayList<SelectCityBean>(); initLocationClient(); mLocationClient.start(); } showIndicator( 0 ); } private void showIndicator( int position ) { layout.removeAllViews(); imageViews = new ArrayList<ImageView>(); pager.setCurrentItem( position ); for( int i = 0; i < citys.size(); i++ ) { ImageView imageView = new ImageView( this ); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( 20, 20 ); lp.leftMargin = 5; imageView.setLayoutParams( lp ); imageViews.add( imageView ); if( i == position ) { setTitle( citys.get( position ).getCityName() + "天氣" ); imageView.setBackgroundResource( R.drawable.page_indicator_focused ); } else { imageView.setBackgroundResource( R.drawable.page_indicator_unfocused ); } layout.addView( imageView ); } } private void setImageBackground( int selectItems ) { for( int i = 0; i < imageViews.size(); i++ ) { if( i == selectItems ) { imageViews.get( i ).setBackgroundResource( R.drawable.page_indicator_focused ); } else { imageViews.get( i ).setBackgroundResource( R.drawable.page_indicator_unfocused ); } } } @Override public boolean onCreateOptionsMenu( Menu menu ) { super.onCreateOptionsMenu( menu ); menu.add( Menu.NONE, Menu.FIRST + 1, 0, "添加城市" ).setShowAsAction( MenuItem.SHOW_AS_ACTION_ALWAYS ); return true; } @Override public boolean onOptionsItemSelected( MenuItem item ) { if( item.getItemId() == Menu.FIRST + 1 ) { Intent intent = new Intent( getApplicationContext(), ChooseCityActivity.class ); intent.putExtra( "key", "value" ); startActivityForResult( intent, 99 ); } return super.onOptionsItemSelected( item ); } @Override protected void onActivityResult( int requestCode, int resultCode, Intent data ) { super.onActivityResult( requestCode, resultCode, data ); if( resultCode == RESULT_OK ) { String city = data.getStringExtra( "selectedCity" ); addCity( city ); } } private void initLocationClient() { mLocationClient = new LocationClient( getApplicationContext() ); // 聲明LocationClient類 myListener = new MyLocationListener(); LocationClientOption option = new LocationClientOption(); option.setLocationMode( LocationMode.Hight_Accuracy ); option.setIsNeedAddress( true ); mLocationClient.setLocOption( option ); mLocationClient.registerLocationListener( myListener ); } @Override protected void onStop() { Log.v( "WeatherAPP", "onStop" ); super.onStop(); if( mLocationClient != null ) mLocationClient.stop(); } @Override protected void onPause() { Log.v( "WeatherAPP", "onPause" ); super.onPause(); } @Override protected void onRestart() { Log.v( "WeatherAPP", "onRestart" ); super.onRestart(); } @Override protected void onResume() { Log.v( "WeatherAPP", "onResume" ); super.onResume(); } @Override protected void onStart() { Log.v( "WeatherAPP", "onStart" ); super.onStart(); } @Override protected void onDestroy() { Log.v( "WeatherAPP", "onDestroy" ); super.onDestroy(); } public class MyLocationListener implements BDLocationListener { @Override public void onReceiveLocation( BDLocation location ) { String city = location.getCity(); addCity( city ); } } private void addCity( String city ) { SelectCityBean cityBean = new SelectCityBean(); cityBean.setCityName( city ); saveCity( cityBean ); if( citys == null ) citys = new ArrayList<SelectCityBean>(); citys.add( cityBean ); mAdapter.notifyDataSetChanged(); showIndicator( citys.size() - 1 ); } private void saveCity( SelectCityBean city ) { DbUtils dbUtils = WeatherApplication.getInstance().getDbUtil(); try { dbUtils.save( city ); } catch( DbException e ) { } } private List<SelectCityBean> readCity() { DbUtils dbUtils = WeatherApplication.getInstance().getDbUtil(); try { return dbUtils.findAll( SelectCityBean.class ); } catch( DbException e ) { return null; } } public class MyAdapter extends FragmentStatePagerAdapter { public MyAdapter( FragmentManager fm ) { super( fm ); } @Override public Fragment getItem( int arg0 ) { WeatherFragment fragment = new WeatherFragment(); fragment.setCity( citys.get( arg0 ).getCityName() ); return fragment; } @Override public int getItemPosition( Object object ) { return POSITION_NONE; } @Override public int getCount() { if( citys == null ) return 0; return citys.size(); } } }
基本上面目全非了,跟以前的代碼徹底不同了,這裏面的主要變更爲:
1. saveCity、readCity再也不從Preference中獲取數據了,而改成從數據庫獲取
2. 增長了MyAdapter以及相關的ViewPager的邏輯
這裏還用到了一個新的SelectCityBean以及兩個圖片資源,
public class SelectCityBean { private int id; private String cityName; public int getId() { return id; } public void setId( int id ) { this.id = id; } public String getCityName() { return cityName; } public void setCityName( String cityName ) { this.cityName = cityName; } }
兩個圖片資源分別表明了當前城市以及其餘城市,
完成以後,運行來看看,我這邊的效果是這樣的:
你能夠試着添加城市看看,是否是這樣的效果。
今天的內容比較少,代碼比較多,你們多多練習一下。
附件是本次的工程文件,點擊下載 http://pan.baidu.com/s/1sj2V5fB 。
此係列文章系本人原創,如需轉載,請註明出處 www.liuzhibang.cn