10天学安卓-第九天
接著昨天的任務,我們今天實現左右滑動可以切換城市的功能。
這里就需要引入新的控件了,Android給我們提供了ViewPager,我們就使用這個,同時,顯示天氣的界面我們也不再使用Activity,而改為Fragment。
Fragment
Fragment可以認為是可復用的UI組件,有自己的布局和完整的生命周期,可以處理本身的事件,但是必須依存于Activity,不能脫離Activity而存在。
?
可以看出來,Fragment的生命周期跟Activity非常相似,并且會隨著Activity的銷毀而銷毀。
?
下面,我們來戰。
首先,新建一個Fragment的子類,取名為WeatherFragment。
public class WeatherFragment extends Fragment {@Overridepublic void onCreate( Bundle savedInstanceState ){super.onCreate( savedInstanceState );}@Overridepublic View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ){return super.onCreateView( inflater, container, savedInstanceState );} }這是用來顯示天氣的界面,而我們之前是直接在Activity中顯示的,需要把這部分代碼給移植到Fragment中。
這是個麻煩的過程,不過不要緊,慢慢來。
新建一個Layout,取名為frag_weather.xml,然后把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"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin" ><ListViewandroid: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中,
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;}@Overridepublic void onCreate( Bundle savedInstanceState ){super.onCreate( savedInstanceState );datas = new ArrayList<WeatherDataBean>();adapter = new WeatherAdapter( getActivity(), datas );}@Overridepublic 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>(){@Overridepublic 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() );}@Overridepublic 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.ViewPagerandroid:id="@+id/viewPager"android:layout_width="fill_parent"android:layout_height="wrap_content" /><LinearLayoutandroid: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;@Overrideprotected 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(){@Overridepublic void onPageSelected( int arg0 ){setTitle( citys.get( arg0 ).getCityName() + "天氣" );setImageBackground( arg0 );}@Overridepublic void onPageScrolled( int arg0, float arg1, int arg2 ){}@Overridepublic 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 );}}}@Overridepublic boolean onCreateOptionsMenu( Menu menu ){super.onCreateOptionsMenu( menu );menu.add( Menu.NONE, Menu.FIRST + 1, 0, "添加城市" ).setShowAsAction( MenuItem.SHOW_AS_ACTION_ALWAYS );return true;}@Overridepublic 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 );}@Overrideprotected 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 );}@Overrideprotected void onStop(){Log.v( "WeatherAPP", "onStop" );super.onStop();if( mLocationClient != null ) mLocationClient.stop();}@Overrideprotected void onPause(){Log.v( "WeatherAPP", "onPause" );super.onPause();}@Overrideprotected void onRestart(){Log.v( "WeatherAPP", "onRestart" );super.onRestart();}@Overrideprotected void onResume(){Log.v( "WeatherAPP", "onResume" );super.onResume();}@Overrideprotected void onStart(){Log.v( "WeatherAPP", "onStart" );super.onStart();}@Overrideprotected void onDestroy(){Log.v( "WeatherAPP", "onDestroy" );super.onDestroy();}public class MyLocationListener implements BDLocationListener{@Overridepublic 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 );}@Overridepublic Fragment getItem( int arg0 ){WeatherFragment fragment = new WeatherFragment();fragment.setCity( citys.get( arg0 ).getCityName() );return fragment;}@Overridepublic int getItemPosition( Object object ){return POSITION_NONE;}@Overridepublic 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
?
總結
以上是生活随笔為你收集整理的10天学安卓-第九天的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 开发笔记“关闭默认键盘”
- 下一篇: 基于jquery的侧边栏分享导航