10天学安卓-第九天

10天学安卓 liuzhibang 2038℃ 0评论

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

这里就需要引入新的控件了,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

 

转载请注明:刘志邦 » 10天学安卓-第九天

喜欢 (9)