仿网易新闻效果android源码分析

一直想知道这种效果到底是如何做出来的,直到看到代码,原来还是动画。从网上找了两份代码,原理基本相同,两份代码中应该有相互参考部分,现在简单解析下,做一个记录,另外,代码中做了些许不妨碍功能的修改(如果有时间的话,自己也会考虑用fragment实现下)。先看下效果图:

这里主要讲解的是以下部分:

先看下注释里面的说明:

/**
 * Android实现局部图片滑动指引效果
 * @Description: 实现以下功能:
 * 1、顶部单张图片左右拖拉滑动;
 * 2、带指引;
 * 3、仅滑动顶部单张图片,不滑动页面,下面的图文内容不动; 
 * 4、类似于新闻客户端的功能

看下它的主Activity里面的全局变量(也就是上面图形):

public class MainActivity extends ActivityGroup implements OnClickListener{
    // 选中的新闻条目
    private TextView mSelectedItem = null;
    // 头部新闻条目的Layout
    private RelativeLayout mHeader = null;
    // 中间新闻主体的Layout
    private RelativeLayout mNewsMainLayout = null;
    private LayoutParams params = null;
    //顶部提示
    private TextView mNetEaseTop = null;
    // 新闻分类
    private TextView mNewsItem = null;
    private TextView mInfoItem = null;
    private TextView mBlogItem = null;
    private TextView mMagezineItem = null;
    private TextView mDomainItem = null;
    private TextView mMoreItem = null;
     
    // 新闻分类中每条分类的宽度
    private int mItemWidth = 0;
    // 条目背景移动开始位置
    private int startX = 0;
    private Intent mIntent = null;
    // 设置新闻主题
    private View mNewsMain = null;

注释比较详细。可以看到这个activity继承自activityGroup类,而activityGroup类在3.0以后是deprecated,所以在开头说想要用fragment重新实现一下。

Deprecated. Use the new Fragment and FragmentManager APIs instead; these are also available on older platforms through the Android compatibility package.

再看onCreate方法:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);      
        // 初始化控件
        initeViews();
    }
     
    /**
     * 初始化控件
     */
    private void initeViews(){
        mNewsItem = (TextView) findViewById(R.id.tv_title_news);
        mInfoItem = (TextView) findViewById(R.id.tv_title_info);
        mBlogItem = (TextView) findViewById(R.id.tv_title_blog);
        mMagezineItem = (TextView) findViewById(R.id.tv_title_magazine);
        mDomainItem = (TextView) findViewById(R.id.tv_title_domain);
        mMoreItem = (TextView) findViewById(R.id.tv_title_more);
         
        mNewsItem.setOnClickListener(this);
        mInfoItem.setOnClickListener(this);
        mBlogItem.setOnClickListener(this);
        mMagezineItem.setOnClickListener(this);
        mDomainItem.setOnClickListener(this);
        mMoreItem.setOnClickListener(this);
 
        // 设置选中条目属性
        mSelectedItem = new TextView(this);
        mSelectedItem.setText(R.string.title_news_category_tops);
        mSelectedItem.setTextColor(Color.WHITE);
        mSelectedItem.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17);
        mSelectedItem.setGravity(Gravity.CENTER);
        mSelectedItem.setWidth((getScreenWidth() - DimensionUtility.dip2px(this, 20)) / 6);
        mSelectedItem.setBackgroundResource(R.drawable.slidebar);
        RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        param.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
         
        mHeader = (RelativeLayout) findViewById(R.id.layout_title_bar);
        mNetEaseTop = (TextView) findViewById(R.id.tv_netease_top);
         
        mHeader.addView(mSelectedItem, param);
         
        // 设置头条新闻主体
        mIntent = new Intent(MainActivity.this, TopicNews.class);
        mNewsMain = getLocalActivityManager().startActivity(
                "TopicNews", mIntent).getDecorView();
        params = new LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        mNewsMainLayout = (RelativeLayout) findViewById(R.id.layout_news_main);
        mNewsMainLayout.addView(mNewsMain, params);
    }

这里所说的选中条目,就是上图中,选中的高亮部分,它其实可以理解为和下面六个是上下两层的关系。而mNetEaseTop是指的

这一块内容,在原代码中,作者并未做这一块和下面内容的同时更新,个人后来加上。设置头条新闻主题下面就是设置默认选择项:第一项(头条新闻)。

再来看一下里面用到的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:weightSum="10" >
 
    <include
        android:id="@+id/header"
        layout="@layout/header" />
 
    <RelativeLayout
        android:id="@+id/layout_news_main"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="9" >
    </RelativeLayout>
 
    <RelativeLayout
        android:id="@+id/layout_bottom"
        android:layout_weight="1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
 
        <RadioGroup
            android:id="@+id/radiogroup"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:background="@drawable/bottombg"
            android:gravity="center_vertical"
            android:orientation="horizontal" >
 
            <RadioButton
                android:id="@+id/radio_news"
                android:layout_width="wrap_content"
                android:background="@drawable/tab_selector_news"
                android:button="@null"
                android:checked="true" />
 
            <RadioButton
                android:id="@+id/radio_topic"
                android:layout_width="wrap_content"
                android:background="@drawable/tab_selector_topic"
                android:button="@null" />
 
            <RadioButton
                android:id="@+id/radio_pic"
                android:layout_width="wrap_content"
                android:background="@drawable/tab_selector_pic"
                android:button="@null" />
 
            <RadioButton
                android:id="@+id/radio_follow"
                android:layout_width="wrap_content"
                android:background="@drawable/tab_selector_follow"
                android:button="@null" />
 
            <RadioButton
                android:id="@+id/radio_vote"
                android:layout_width="wrap_content"
                android:background="@drawable/tab_selector_vote"
                android:button="@null" />
        </RadioGroup>
    </RelativeLayout>
 
</LinearLayout>

中间的layout_new_main就是mNewsMainLayout,起到一个占位的作用,下面的RadioGroup就是最下面的标记栏。里面用到的布局文件主要是header.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >
 
    <RelativeLayout
        android:id="@+id/layout_top"
        android:layout_width="match_parent"
        android:layout_height="40dip"
        android:background="#990000" >
 
        <TextView
            android:id="@+id/tv_netease_top"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dip"
            android:textSize="20sp"
            android:textColor="@android:color/white"
            android:text="@string/news_top_left_text1" />
 
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@+id/tv_netease_top"
            android:text="@string/news_top_left_text2"
            android:textColor="@android:color/white"
            android:textSize="20sp" />
 
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:src="@drawable/duoyun"
            android:contentDescription="@string/img_duoyun_desc" />
         
    </RelativeLayout>
 
    <RelativeLayout
        android:id="@+id/layout_title_bar"
        android:layout_width="fill_parent"
        android:layout_height="40dip"
        android:paddingLeft="5dip"
        android:paddingRight="5dip"
        android:background="@drawable/bg_header_top">
 
        <LinearLayout
            android:id="@+id/header_item"
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal" >
 
            <RelativeLayout
                android:id="@+id/layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1" >
 
                <TextView
                    android:id="@+id/tv_title_news"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_centerInParent="true"
                    style="@style/header_title_style"
                    android:gravity="center"
                    android:text="@string/title_news_category_tops" />
                 
            </RelativeLayout>
 
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1" >
 
                <TextView
                    android:id="@+id/tv_title_info"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_centerInParent="true"
                    style="@style/header_title_style"
                    android:gravity="center"
                    android:text="@string/title_news_category_info" />
                 
            </RelativeLayout>
 
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1" >
 
                <TextView
                    android:id="@+id/tv_title_blog"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_centerInParent="true"
                    style="@style/header_title_style"
                    android:gravity="center"
                    android:text="@string/title_news_category_blog" />
                 
            </RelativeLayout>
 
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1" >
 
                <TextView
                    android:id="@+id/tv_title_magazine"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_centerInParent="true"
                    style="@style/header_title_style"
                    android:gravity="center"
                    android:text="@string/title_news_category_magazine" />
                 
            </RelativeLayout>
 
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1" >
 
                <TextView
                    android:id="@+id/tv_title_domain"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_centerInParent="true"
                    style="@style/header_title_style"
                    android:gravity="center"
                    android:text="@string/title_news_category_domain" />
                 
            </RelativeLayout>
 
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1" >
 
                <TextView
                    android:id="@+id/tv_title_more"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_centerInParent="true"
                    style="@style/header_title_style"
                    android:gravity="center"
                    android:text="@string/title_news_category_more" />
            </RelativeLayout>
        </LinearLayout>
    </RelativeLayout>
</LinearLayout>

比较简单的布局,不详述。

上面代码设置选中项宽带:

mSelectedItem.setWidth((getScreenWidth() - DimensionUtility.dip2px(this, 20)) / 6);

用到了getScreenWidth方法:

/**
     * 获取屏幕的宽度
     * @return
     */
    private int getScreenWidth(){
        WindowManager windowManager = getWindowManager();
        Display display = windowManager.getDefaultDisplay();
//      Point point = new Point();
//      display.getSize(point);
//      int screenWidth = point.x; 
        int screenWidth = display.getWidth();
        return screenWidth;
    }

display的getWidth方法在3.0中好像也没deprecated。可以使用注释掉的代码获取屏幕宽度。

下面是最重要的部分点击切换:

// 新闻分类事件监听
    @Override
    public void onClick(View v) {
        mItemWidth = findViewById(R.id.layout).getWidth();
         
        switch (v.getId()) {
        case R.id.tv_title_news:
            //动画滑动
            ImageAnimation.SetImageSlide(mSelectedItem, startX, 0, 0, 0);
            //设置滑动后动画开始位置
            startX = 0;
            //设置选中项显示文字,也就是高亮部分文字
            mSelectedItem.setText(R.string.title_news_category_tops);
            //设置左上角提示文字
            mNetEaseTop.setText(R.string.title_news_category_tops);
             
            // 显示头条信息
            mIntent.setClass(MainActivity.this, TopicNews.class);
            mNewsMain = getLocalActivityManager().startActivity(
                    "TopicNews", mIntent).getDecorView();
            break;
        case R.id.tv_title_info:
            ImageAnimation.SetImageSlide(mSelectedItem, startX, mItemWidth, 0, 0);
            startX = mItemWidth;
            mSelectedItem.setText(R.string.title_news_category_info);
            mNetEaseTop.setText(R.string.title_news_category_info);
             
            // 显示资讯信息
            mIntent.setClass(MainActivity.this, InfoNews.class);
            mNewsMain = getLocalActivityManager().startActivity(
                    "InfoNews", mIntent).getDecorView();
            break;
        case R.id.tv_title_blog:
            ImageAnimation.SetImageSlide(mSelectedItem, startX, mItemWidth * 2, 0, 0);
            startX = mItemWidth * 2;
            mSelectedItem.setText(R.string.title_news_category_blog);
            mNetEaseTop.setText(R.string.title_news_category_blog);
             
            // 显示博客信息
            mIntent.setClass(MainActivity.this, BlogNews.class);
            mNewsMain = getLocalActivityManager().startActivity(
                    "BlogNews", mIntent).getDecorView();
            break;
        case R.id.tv_title_magazine:
            ImageAnimation.SetImageSlide(mSelectedItem, startX, mItemWidth * 3, 0, 0);
            startX = mItemWidth * 3;
            mSelectedItem.setText(R.string.title_news_category_magazine);
            mNetEaseTop.setText(R.string.title_news_category_magazine);
             
            // 显示杂志信息
            mIntent.setClass(MainActivity.this, MagazineNews.class);
            mNewsMain = getLocalActivityManager().startActivity(
                    "MagazineNews", mIntent).getDecorView();
            break;
        case R.id.tv_title_domain:
            ImageAnimation.SetImageSlide(mSelectedItem, startX, mItemWidth * 4, 0, 0);
            startX = mItemWidth * 4;
            mSelectedItem.setText(R.string.title_news_category_domain);
            mNetEaseTop.setText(R.string.title_news_category_domain);
            // 显示业界信息
            mIntent.setClass(MainActivity.this, DomainNews.class);
            mNewsMain = getLocalActivityManager().startActivity(
                    "DomainNews", mIntent).getDecorView();
            break;
        case R.id.tv_title_more:
            ImageAnimation.SetImageSlide(mSelectedItem, startX, mItemWidth * 5, 0, 0);
            startX = mItemWidth * 5;
            mSelectedItem.setText(R.string.title_news_category_more);
            mNetEaseTop.setText(R.string.title_news_category_more);
             
            // 显示更多信息
            mIntent.setClass(MainActivity.this, MoreNews.class);
            mNewsMain = getLocalActivityManager().startActivity(
                    "MoreNews", mIntent).getDecorView();
            break;
        default:
            break;
        }       
        // 更换Layout中的新闻主体
        mNewsMainLayout.removeAllViews();
        mNewsMainLayout.addView(mNewsMain, params);
    }

在注释中,解释的已经比较清楚了,看一下ImageAnimation:

public class ImageAnimation {
    /**
     * 设置图像移动动画效果
     * @param v
     * @param startX
     * @param toX
     * @param startY
     * @param toY
     */
    public static void SetImageSlide(View v, int startX, int toX, int startY, int toY) {
        TranslateAnimation anim = new TranslateAnimation(startX, toX, startY, toY);
        anim.setDuration(100);
        anim.setFillAfter(true);
        v.startAnimation(anim);
    }
}

就是一个简单的移动动画。这样就是简单的顶部标示就完成了,接下来要分析如下:

这个代码在TopicNews中,先看下使用到的全局变量:

public class TopicNews extends Activity{
    // 滑动图片的集合
    private ArrayList<View> mImagePageViewList = null;
    private ViewGroup mMainView = null;
    private ViewPager mViewPager = null;
    // 当前ViewPager索引
//  private int pageIndex = 0; 
     
    // 包含圆点图片的View
    private ViewGroup mImageCircleView = null;
    private ImageView\[\] mImageCircleViews = null; 
     
    // 滑动标题
    private TextView mSlideTitle = null;
     
    // 布局设置类
    private SlideImageLayout mSlideLayout = null;
    // 数据解析类
    private NewsXmlParser mParser = null;

 里面的viewPager类是用于滑动控件,SlideImageLayout类是用于上面图片和下面标志点的布局。NewsXmlParser类提供数据。

看一下onCreate方法:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setTheme(android.R.style.Theme_Translucent_NoTitleBar);     
    // 初始化
    initeViews();
}
 
/**
 * 初始化
 */
private void initeViews(){
    // 滑动图片区域
    mImagePageViewList = new ArrayList<View>();
    LayoutInflater inflater = getLayoutInflater();  
    mMainView = (ViewGroup)inflater.inflate(R.layout.page_topic_news, null);
    mViewPager = (ViewPager) mMainView.findViewById(R.id.image_slide_page);  
     
    // 圆点图片区域
    mParser = new NewsXmlParser();
    int length = mParser.getSlideImages().length;
    mImageCircleViews = new ImageView\[length\];
    mImageCircleView = (ViewGroup) mMainView.findViewById(R.id.layout_circle_images);
    mSlideLayout = new SlideImageLayout(TopicNews.this);
    mSlideLayout.setCircleImageLayout(length);
     
    for(int i = 0; i < length; i++){
        mImagePageViewList.add(mSlideLayout.getSlideImageLayout(mParser.getSlideImages()\[i\]));
        mImageCircleViews\[i\] = mSlideLayout.getCircleImageLayout(i);
        mImageCircleView.addView(mSlideLayout.getLinearLayout(mImageCircleViews\[i\], 10, 10));
    }
     
    // 设置默认的滑动标题
    mSlideTitle = (TextView) mMainView.findViewById(R.id.tvSlideTitle);
    mSlideTitle.setText(mParser.getSlideTitles()\[0\]);
     
    setContentView(mMainView);
     
    // 设置ViewPager
    mViewPager.setAdapter(new SlideImageAdapter());  
    mViewPager.setOnPageChangeListener(new ImagePageChangeListener());
}

看一下远点图片区域:

// 圆点图片区域
        mParser = new NewsXmlParser();
        int length = mParser.getSlideImages().length;
        mImageCircleViews = new ImageView\[length\];
        mImageCircleView = (ViewGroup) mMainView.findViewById(R.id.layout_circle_images);
        mSlideLayout = new SlideImageLayout(TopicNews.this);
        mSlideLayout.setCircleImageLayout(length);
         
        for(int i = 0; i < length; i++){
            mImagePageViewList.add(mSlideLayout.getSlideImageLayout(mParser.getSlideImages()\[i\]));
            mImageCircleViews\[i\] = mSlideLayout.getCircleImageLayout(i);
            mImageCircleView.addView(mSlideLayout.getLinearLayout(mImageCircleViews\[i\], 10, 10));
        }

里面主要是调用了NewsXmlParser类和SlideImageLayout的方法,那就先看下NewsXmlParser的getSlideImages方法:

public int\[\] getSlideImages(){
        return slideImages;
    }

这里的slideImage是在类中定义好的:

// 滑动图片的集合,这里设置成了固定加载,当然也可动态加载。
    private int\[\] slideImages = {
            R.drawable.image01,
            R.drawable.image02,
            R.drawable.image03,
            R.drawable.image04,
            R.drawable.image05};

那看一下用到的SlideImageLayout类的getSlideImageLayout:获取图片的布局:

/**
     * 生成滑动图片区域布局
     * @param id
     * @return
     */
    public View getSlideImageLayout(int id){
        // 包含TextView的LinearLayout
        LinearLayout imageLinerLayout = new LinearLayout(mContext);
        LinearLayout.LayoutParams imageLinerLayoutParames = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT, 
                LinearLayout.LayoutParams.WRAP_CONTENT,
                1);
         
        ImageView iv = new ImageView(mContext);
        iv.setBackgroundResource(id);
        iv.setOnClickListener(new ImageOnClickListener());
        imageLinerLayout.addView(iv,imageLinerLayoutParames);
        mImageList.add(iv);
         
        return imageLinerLayout;
    }

创建一个layout,然后再创建一个imageView,把ImageView加入到layout中,然后返回layout。同理,我们再看下set和getCircleImageLayout:

* 设置圆点个数
    * @param size
    */
   public void setCircleImageLayout(int size){
       mImageViews = new ImageView\[size\];
   }
    
   /**
    * 生成圆点图片区域布局对象
    * @param index
    * @return
    */
   public ImageView getCircleImageLayout(int index){
       mImageView = new ImageView(mContext);  
       mImageView.setLayoutParams(new LayoutParams(10,10));
       mImageView.setScaleType(ScaleType.FIT_XY);
        
       mImageViews\[index\] = mImageView;
         
       if (index == 0) {  
           //默认选中第一张图片
           mImageViews\[index\].setBackgroundResource(R.drawable.dot_selected);  
       } else {  
           mImageViews\[index\].setBackgroundResource(R.drawable.dot_none);  
       }  
         
       return mImageViews\[index\];
   }

获取圆点图片的Image,然后返回。

在initViews中还有设置滑动图片标题:

// 设置默认的滑动标题
        mSlideTitle = (TextView) mMainView.findViewById(R.id.tvSlideTitle);
        mSlideTitle.setText(mParser.getSlideTitles()\[0\]);
         
        setContentView(mMainView);

最后是设置Viewpager的Adapter还有监听

// 设置ViewPager
        mViewPager.setAdapter(new SlideImageAdapter());  
        mViewPager.setOnPageChangeListener(new ImagePageChangeListener());

先来看下SlideImageAdapter类:

// 滑动图片数据适配器
    private class SlideImageAdapter extends PagerAdapter {  
        @Override  
        public int getCount() { 
            return mImagePageViewList.size();  
        }  
   
        @Override  
        public boolean isViewFromObject(View view, Object object) {  
            return view == object;  
        }  
   
        @Override  
        public int getItemPosition(Object object) {  
            return super.getItemPosition(object);  
        }  
   
        @Override  
        public void destroyItem(View view, int arg1, Object arg2) {  
            ((ViewPager) view).removeView(mImagePageViewList.get(arg1));  
        }  
   
        @Override  
        public Object instantiateItem(View view, int position) {  
            ((ViewPager) view).addView(mImagePageViewList.get(position));
             
            return mImagePageViewList.get(position);  
        }  
   
        @Override  
        public void restoreState(Parcelable arg0, ClassLoader arg1) {  
   
        }  
   
        @Override  
        public Parcelable saveState() {  
            return null;  
        }  
   
        @Override  
        public void startUpdate(View arg0) {  
        }  
   
        @Override  
        public void finishUpdate(View arg0) {  
        }  
    }

一个典型的适配器类,主要看下面两个方法:

@Override  
        public void destroyItem(View view, int arg1, Object arg2) {  
            ((ViewPager) view).removeView(mImagePageViewList.get(arg1));  
        }  
   
        @Override  
        public Object instantiateItem(View view, int position) {  
            ((ViewPager) view).addView(mImagePageViewList.get(position));
             
            return mImagePageViewList.get(position);  
        }

实例化Item和销毁Item。我们在initViews方法里面为mImagePageViewList里面加载了很多view,在这里取出,加入到ViewPager中去。

其实他的滑动监听事件特别简单,就是改变下选中图片、标识圆点和标题文字:

// 滑动页面更改事件监听器
    private class ImagePageChangeListener implements OnPageChangeListener {
        @Override  
        public void onPageScrollStateChanged(int arg0) {  
        }  
   
        @Override  
        public void onPageScrolled(int arg0, float arg1, int arg2) {  
        }  
   
        @Override  
        public void onPageSelected(int index) {  
//          pageIndex = index;
            mSlideLayout.setPageIndex(index);
            mSlideTitle.setText(mParser.getSlideTitles()\[index\]);
             
            for (int i = 0; i < mImageCircleViews.length; i++) {  
                mImageCircleViews\[index\].setBackgroundResource(R.drawable.dot_selected);
                 
                if (index != i) {  
                    mImageCircleViews\[i\].setBackgroundResource(R.drawable.dot_none);  
                }  
            }
        }  
    }

还有,在网易新闻里,有个底部标记栏:

这个功能是如何实现的呢?

<RelativeLayout
        android:id="@+id/layout_bottom"
        android:layout_weight="1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
 
        <RadioGroup
            android:id="@+id/radiogroup"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:background="@drawable/bottombg"
            android:gravity="center_vertical"
            android:orientation="horizontal" >
 
            <RadioButton
                android:id="@+id/radio_news"
                android:layout_width="wrap_content"
                android:background="@drawable/tab_selector_news"
                android:button="@null"
                android:checked="true" />
 
            <RadioButton
                android:id="@+id/radio_topic"
                android:layout_width="wrap_content"
                android:background="@drawable/tab_selector_topic"
                android:button="@null" />
 
            <RadioButton
                android:id="@+id/radio_pic"
                android:layout_width="wrap_content"
                android:background="@drawable/tab_selector_pic"
                android:button="@null" />
 
            <RadioButton
                android:id="@+id/radio_follow"
                android:layout_width="wrap_content"
                android:background="@drawable/tab_selector_follow"
                android:button="@null" />
 
            <RadioButton
                android:id="@+id/radio_vote"
                android:layout_width="wrap_content"
                android:background="@drawable/tab_selector_vote"
                android:button="@null" />
        </RadioGroup>
    </RelativeLayout>

其中background图片:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
 
    <item android:drawable="@drawable/current_topic_tab" android:state_checked="true"/>
    <item android:drawable="@drawable/back_topic_tab" android:state_checked="false"/>
 
</selector>

切换代码:

@Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
 
        switch (checkedId) {
        case R.id.radio_news:
            ImageAnimation.SetImageSlide(mImageView, startLeft, 0, 0, 0);
            startLeft = 0;
            break;
        case R.id.radio_topic:
            ImageAnimation.SetImageSlide(mImageView, startLeft, mImageView.getWidth(), 0, 0);
            startLeft = mImageView.getWidth();
         
            break;
        case R.id.radio_pic:
            ImageAnimation.SetImageSlide(mImageView, startLeft, mImageView.getWidth() * 2, 0, 0);
            startLeft = mImageView.getWidth() * 2;
            break;
        case R.id.radio_follow:
            ImageAnimation.SetImageSlide(mImageView, startLeft, mImageView.getWidth() * 3, 0, 0);
            startLeft = mImageView.getWidth() * 3;
            break;
        case R.id.radio_vote:
            ImageAnimation.SetImageSlide(mImageView, startLeft, mImageView.getWidth() * 4, 0, 0);
            startLeft = mImageView.getWidth() * 4;
            break;
 
        default:
            break;
        }
    

最后代码下载地址:

http://download.csdn.net/detail/aomandeshangxiao/4751356