10天学安卓-第九天

原文: 10天学安卓-第九天

接着昨天的任务,我们今天实现左右滑动可以切换城市的功能。

这里就需要引入新的控件了,Android给我们提供了ViewPager,我们就使用这个,同时,显示天气的界面我们也不再使用Activity,而改为Fragment。

Fragment

Fragment可以认为是可复用的UI组件,有自己的布局和完整的生命周期,可以处理本身的事件,但是必须依存于Activity,不能脱离Activity而存在。

08162501-0d1530c0e072468b8b0a68c1c8913bce

 

可以看出来,Fragment的生命周期跟Activity非常相似,并且会随着Activity的销毁而销毁。

 

下面,我们来战。

首先,新建一个Fragment的子类,取名为WeatherFragment。

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中。

这是个麻烦的过程,不过不要紧,慢慢来。

新建一个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"  >



    <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中,

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;

    }

}

 

两个图片资源分别代表了当前城市以及其他城市,

page_indicator_focusedpage_indicator_unfocused

 

完成之后,运行来看看,我这边的效果是这样的:

device-2015-01-27-084239

 

 

你可以试着添加城市看看,是不是这样的效果。

 

今天的内容比较少,代码比较多,大家多多练习一下。

 

附件是本次的工程文件,点击下载 http://pan.baidu.com/s/1sj2V5fB 。

此系列文章系本人原创,如需转载,请注明出处 www.liuzhibang.cn

 

你可能感兴趣的:(安卓)