模仿网易新闻客户端(RSS版)(一)

2012033100313348.png       2012033100314616.png      2012033100315576.png 

2012033100320229.png       2012033100321095.png 

三、底部类似TabHost组件切换效果的实现

为了便于大家亲自动手实践,这里的讲解顺序就按照开发的顺序来讲,所以先做这个底部的“TabHost”,然后再具体来实现里面的五个页面布局。

类似于图3到图5三张图片所示,当点击“新闻”或者“话题”或者“投票”的时候,有个稍微透明的红色背景的ImageView做相应的移动。这其实就是给ImageView设置了一个位移动画,当点击事件触发的时候,首先切换点击后的图片(有点类似于按下效果的图片),然后开始移动铺在上面的红色图片,让用户感觉到有移动的过程,增强用户体验。

关于这个位移动画,需要用到TranslateAnimation类,移动的核心代码也就几行,因为这个移动功能不但在底部控件上使用,而且在顶部也使用了,所以,为了以后使用方便,我们把它单独定义在一个类里面MoveBg.java
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
View Code
 
package com.and.netease.utils;
 
import android.view.View;
import android.view.animation.TranslateAnimation;
 
public class MoveBg {
    /**
      * 移动方法
      *
      * @param v
      *            需要移动的View
      * @param startX
      *            起始x坐标
      * @param toX
      *            终止x坐标
      * @param startY
      *            起始y坐标
      * @param toY
      *            终止y坐标
      */
    public static void moveFrontBg(View v, int startX, int toX, int startY, int toY) {
         TranslateAnimation anim = new TranslateAnimation(startX, toX, startY, toY);
         anim.setDuration( 200 );
         anim.setFillAfter( true );
         v.startAnimation(anim);
    }
}


里面的各个参数有相应的说明。

然后就来开发这个带有TabHost功能的组件。根据文档http://developer.android.com/resources/tutorials/views/hello-tabwidget.html说明,在xml中定义TabHost的时候,必须使用TabWidget和FrameLayou两个组件,而且它们的id也应该是android:id="@android:id/tabs"和android:id="@android:id/tabcontent",由于系统提供的TabHost界面不怎么好看,所以这里想到自己来定义它,但是这两个组件是不可以不写的,这里,把TabWidget界面隐藏掉了,取而代之的是RadioGroup组件来实现底部类似于TabHost的控件。具体布局代码如main.xml
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
View Code
 
<?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" >
 
    <TabHost
         android:id= "@android:id/tabhost"
         android:layout_width= "fill_parent"
         android:layout_height= "fill_parent" >
 
         <LinearLayout
             android:layout_width= "fill_parent"
             android:layout_height= "fill_parent"
             android:orientation= "vertical" >
 
             <FrameLayout
                android:id= "@android:id/tabcontent"
                android:layout_width= "fill_parent"
                android:layout_height= "0.0dip"
                android:layout_weight= "1.0" >
             </FrameLayout>
 
             <TabWidget
                android:id= "@android:id/tabs"
                android:layout_width= "fill_parent"
                android:layout_height= "wrap_content"
                android:visibility= "gone" />
 
             <RelativeLayout
                android:id= "@+id/layout_bottom"
                android:layout_width= "fill_parent"
                android:layout_height= "wrap_content" >
 
                <RadioGroup
                     android:id= "@+id/radiogroup"
                     android:layout_width= "fill_parent"
                     android:layout_height= "wrap_content"
                     android:layout_gravity= "bottom"
                     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>
    </TabHost>
 
</LinearLayout>


注意里面的RadioButton组件,当初测试的时候没有设置android:button="@null",只设置了background="@drawable/..."属性(这是一个selector属性,可以在xml文件中定义一些控件的按下效果,或者获取焦点等不同状态下的资源),出现点击不切换图片的问题。

对应的selector文件对应如下tab_selector_news.xml
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
View Code
 
<?xml version= "1.0" encoding= "utf-8" ?>
<selector xmlns:android= "http://schemas.android.com/apk/res/android" >
 
    <item android:drawable= "@drawable/current_news_tab" android:state_checked= "true" />
    <item android:drawable= "@drawable/back_news_tab" android:state_checked= "false" />
 
</selector>


其它几个,只是替换不同的图片资源罢了,不再一一列出。这些资源文件放在res目录下的drawable文件夹下(如果没有,则新建)

有了布局文件,还需要在Activity中设置一下,为每个TabHost添加具体的Tab页面,如下
?
代码片段,双击复制
01
02
03
04
05
06
tabHost = getTabHost();
         tabHost.addTab(tabHost.newTabSpec( "news" ).setIndicator( "News" ).setContent( new Intent( this , TabNewsActivity. class )));
         tabHost.addTab(tabHost.newTabSpec( "topic" ).setIndicator( "Topic" ).setContent( new Intent( this , TabTopicActivity. class )));
         tabHost.addTab(tabHost.newTabSpec( "picture" ).setIndicator( "Picture" ).setContent( new Intent( this , TabPicActivity. class )));
         tabHost.addTab(tabHost.newTabSpec( "follow" ).setIndicator( "Follow" ).setContent( new Intent( this , TabFollowActivity. class )));
         tabHost.addTab(tabHost.newTabSpec( "vote" ).setIndicator( "Vote" ).setContent( new Intent( this , TabVoteActivity. class )));


当然,相应的目标Activity自然暂且随意创建

然后为RadioGroup设置选择改变事件监听器,当选择改变,改变TabHost中当前显示的Activity页面

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private OnCheckedChangeListener checkedChangeListener = new OnCheckedChangeListener() {
 
         @Override
         public void onCheckedChanged(RadioGroup group, int checkedId) {
             switch (checkedId) {
             case R.id.radio_news:
                tabHost.setCurrentTabByTag( "news" );
                break ;
             case R.id.radio_topic:
                tabHost.setCurrentTabByTag( "topic" );
                break ;
             case R.id.radio_pic:
                tabHost.setCurrentTabByTag( "picture" );
                break ;
             case R.id.radio_follow:
                tabHost.setCurrentTabByTag( "follow" );
                break ;
             case R.id.radio_vote:
                tabHost.setCurrentTabByTag( "vote" );
                break ;
 
             default :
                break ;
             }
         }
    };


至此就实现了一个自定义的“TabHost”,接下来再添加那个移动的特效

页面上的 
2012033100363827.png  是一个RelativeLayout布局,我只是在这个layout上面添加了一个ImageView,然后当点击的时候,移动它的位置来实现效果

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private OnCheckedChangeListener checkedChangeListener = new OnCheckedChangeListener() {
 
         @Override
         public void onCheckedChanged(RadioGroup group, int checkedId) {
             switch (checkedId) {
             case R.id.radio_news:
                tabHost.setCurrentTabByTag( "news" );
//                moveFrontBg(img, startLeft, 0, 0, 0);
                MoveBg.moveFrontBg(img, startLeft, 0 , 0 , 0 );
                startLeft = 0 ;
                break ;
             case R.id.radio_topic:
                tabHost.setCurrentTabByTag( "topic" );
                MoveBg.moveFrontBg(img, startLeft, img.getWidth(), 0 , 0 );
                startLeft = img.getWidth();
                break ;
             case R.id.radio_pic:
                tabHost.setCurrentTabByTag( "picture" );
                MoveBg.moveFrontBg(img, startLeft, img.getWidth() * 2 , 0 , 0 );
                startLeft = img.getWidth() * 2 ;
                break ;
             case R.id.radio_follow:
                tabHost.setCurrentTabByTag( "follow" );
                MoveBg.moveFrontBg(img, startLeft, img.getWidth() * 3 , 0 , 0 );
                startLeft = img.getWidth() * 3 ;
                break ;
             case R.id.radio_vote:
                tabHost.setCurrentTabByTag( "vote" );
                MoveBg.moveFrontBg(img, startLeft, img.getWidth() * 4 , 0 , 0 );
                startLeft = img.getWidth() * 4 ;
                break ;
 
             default :
                break ;
             }
         }
    };

此处要记住移动的初始位置和起始位置就行了。Y坐标轴上不变,只横向移动。至此,这个功能实现完了

四、顶部按下效果实现

顶部和底部那个自定义控件的实现效果大体是一样的,唯一不同的就是,这个移动的不再是ImageView,而是一个TextView,在移动完成之后还需要改变这个TextView上的文字,仅此而已,而已文件如下layout_news.xml
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<?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" >
 
    <RelativeLayout
         android:id= "@+id/layout_top"
         android:layout_width= "match_parent"
         android:layout_height= "40dip"
         android:background= "#990000" >
 
         <ImageView
             android:id= "@+id/img_netease_top"
             android:layout_width= "wrap_content"
             android:layout_height= "wrap_content"
             android:layout_centerVertical= "true"
             android:layout_marginLeft= "10dip"
             android:src= "@drawable/netease_top" />
 
         <TextView
             android:layout_width= "wrap_content"
             android:layout_height= "wrap_content"
             android:layout_centerVertical= "true"
             android:layout_toRightOf= "@+id/img_netease_top"
             android:text= "@string/news_top_left_text"
             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" />
    </RelativeLayout>
 
    <RelativeLayout
         android:id= "@+id/layout_title_bar"
         android:layout_width= "fill_parent"
         android:layout_height= "35dip"
         android:background= "@android:color/white"
         android:paddingLeft= "10dip"
         android:paddingRight= "10dip" >
 
         <LinearLayout
             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_bar_news"
                     android:layout_width= "wrap_content"
                     android:layout_height= "wrap_content"
                     android:layout_centerInParent= "true"
                     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_bar_sport"
                     android:layout_width= "wrap_content"
                     android:layout_height= "wrap_content"
                     android:layout_centerInParent= "true"
                     android:text= "@string/title_news_category_sport" />
             </RelativeLayout>
 
             <RelativeLayout
                android:layout_width= "match_parent"
                android:layout_height= "match_parent"
                android:layout_weight= "1" >
 
                <TextView
                     android:id= "@+id/tv_title_bar_play"
                     android:layout_width= "wrap_content"
                     android:layout_height= "wrap_content"
                     android:layout_centerInParent= "true"
                     android:text= "@string/title_news_category_play" />
             </RelativeLayout>
 
             <RelativeLayout
                android:layout_width= "match_parent"
                android:layout_height= "match_parent"
                android:layout_weight= "1" >
 
                <TextView
                     android:id= "@+id/tv_title_bar_finance"
                     android:layout_width= "wrap_content"
                     android:layout_height= "wrap_content"
                     android:layout_centerInParent= "true"
                     android:text= "@string/title_news_category_finance" />
             </RelativeLayout>
 
             <RelativeLayout
                android:layout_width= "match_parent"
                android:layout_height= "match_parent"
                android:layout_weight= "1" >
 
                <TextView
                     android:id= "@+id/tv_title_bar_science"
                     android:layout_width= "wrap_content"
                     android:layout_height= "wrap_content"
                     android:layout_centerInParent= "true"
                     android:text= "@string/title_news_category_science" />
             </RelativeLayout>
 
             <RelativeLayout
                android:layout_width= "match_parent"
                android:layout_height= "match_parent"
                android:layout_weight= "1" >
 
                <TextView
                     android:id= "@+id/tv_title_bar_more"
                     android:layout_width= "wrap_content"
                     android:layout_height= "wrap_content"
                     android:layout_centerInParent= "true"
                     android:text= "@string/title_news_category_more" />
             </RelativeLayout>
         </LinearLayout>
    </RelativeLayout>
 
</LinearLayout>


对应的Activity代码TabNewsActivity.java
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package com.and.netease;
 
import com.and.netease.utils.MoveBg;
 
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
 
public class TabNewsActivity extends Activity {
    RelativeLayout layout;
    TextView tv_front; //需要移动的View
 
    TextView tv_bar_news;
    TextView tv_bar_sport;
    TextView tv_bar_play;
    TextView tv_bar_finance;
    TextView tv_bar_science;
    TextView tv_bar_more;
 
    int avg_width = 0 ; // 用于记录平均每个标签的宽度,移动的时候需要
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.layout_news);
 
         initViews();
    }
 
    private void initViews() {
         layout = (RelativeLayout) findViewById(R.id.layout_title_bar);
 
         tv_bar_news = (TextView) findViewById(R.id.tv_title_bar_news);
         tv_bar_sport = (TextView) findViewById(R.id.tv_title_bar_sport);
         tv_bar_play = (TextView) findViewById(R.id.tv_title_bar_play);
         tv_bar_finance = (TextView) findViewById(R.id.tv_title_bar_finance);
         tv_bar_science = (TextView) findViewById(R.id.tv_title_bar_science);
         tv_bar_more = (TextView) findViewById(R.id.tv_title_bar_more);
 
         tv_bar_news.setOnClickListener(onClickListener);
         tv_bar_sport.setOnClickListener(onClickListener);
         tv_bar_play.setOnClickListener(onClickListener);
         tv_bar_finance.setOnClickListener(onClickListener);
         tv_bar_science.setOnClickListener(onClickListener);
         tv_bar_more.setOnClickListener(onClickListener);
 
         tv_front = new TextView( this );
         tv_front.setBackgroundResource(R.drawable.slidebar);
         tv_front.setTextColor(Color.WHITE);
         tv_front.setText( "头条" );
         tv_front.setGravity(Gravity.CENTER);
         RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
         param.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
         layout.addView(tv_front, param);
 
    }
 
    private OnClickListener onClickListener = new OnClickListener() {
         int startX; //移动的起始位置
 
         @Override
         public void onClick(View v) {
             avg_width = findViewById(R.id.layout).getWidth();
             switch (v.getId()) {
             case R.id.tv_title_bar_news:
                MoveBg.moveFrontBg(tv_front, startX, 0 , 0 , 0 );
                startX = 0 ;
                tv_front.setText(R.string.title_news_category_tops);
                break ;
             case R.id.tv_title_bar_sport:
                MoveBg.moveFrontBg(tv_front, startX, avg_width, 0 , 0 );
                startX = avg_width;
                tv_front.setText(R.string.title_news_category_sport);
                break ;
             case R.id.tv_title_bar_play:
                MoveBg.moveFrontBg(tv_front, startX, avg_width * 2 , 0 , 0 );
                startX = avg_width * 2 ;
                tv_front.setText(R.string.title_news_category_play);
                break ;
             case R.id.tv_title_bar_finance:
                MoveBg.moveFrontBg(tv_front, startX, avg_width * 3 , 0 , 0 );
                startX = avg_width * 3 ;
                tv_front.setText(R.string.title_news_category_finance);
                break ;
             case R.id.tv_title_bar_science:
                MoveBg.moveFrontBg(tv_front, startX, avg_width * 4 , 0 , 0 );
                startX = avg_width * 4 ;
                tv_front.setText(R.string.title_news_category_science);
                break ;
             case R.id.tv_title_bar_more:
                MoveBg.moveFrontBg(tv_front, startX, avg_width * 5 , 0 , 0 );
                startX = avg_width * 5 ;
                tv_front.setText(R.string.title_news_category_more);
                break ;
 
             default :
                break ;
             }
 
         }
    };
 
}


五、总结

通过这种例子,我个人总结有两点需要掌握,一个是TranslateAnimation类的使用,另一个就是布局文件的嵌套使用,经验多了,慢慢就会有感觉了。以上仅代表我个人的一点点想法和总结,还请各位多多指教。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值