效果图:

    

这里的后台管理用的是duducat,大家可以去百度看说明。图片,文字都在duducat后台服务器上,可以自己修改的。(PS:图片这里是随便找的)

http://www.duducat.com/

我就直接上代码了,如果有不懂的可以联系我。

MainActivity.java

public class MainActivity extends FragmentActivity implements ViewPager.OnPageChangeListener, TabHost.OnTabChangeListener {
private TabHost tabHost;
private HorizontalScrollView hScrollView;
private ViewPager viewPager;
private PagerAdapter pagerAdapter;
private HashMap<String, TabInfo> mapTabInfo = new HashMap<String, TabInfo>(); /**
* tab顶部标签的基本信息
*/
private class TabInfo {
private String tag;
public View On;
public View Off;
public View Tab; public TabInfo(String tag, Class<?> clazz, Bundle args) {
this.tag = tag;
}
} public class TabFactory implements TabHost.TabContentFactory {
private final Context mContext; public TabFactory(Context context) {
mContext = context;
} public View createTabContent(String tag) {
View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
} protected void onCreate(Bundle savedInstanceState) {
//注册嘟嘟猫后台管理
ActiveConfig.register(MainActivity.this, "19K3Me8Z", "hVAjCHK55TaB66YR");
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); hScrollView = (HorizontalScrollView) findViewById(R.id.hScrollView);
//初始化viewpager
initViewPager();
//初始化tabhost
initTabHost(savedInstanceState);
} protected void onSaveInstanceState(Bundle outState) {
outState.putString("tab", tabHost.getCurrentTabTag());
super.onSaveInstanceState(outState);
} private void initViewPager() {
//封装Fragment对象
List<Fragment> fragments = new Vector<Fragment>(); for (int i = 0; i < 12; i++) {
Bundle budle = new Bundle();
budle.putInt("i", i);
Fragment f = Fragment.instantiate(MainActivity.this, HoroscopeFragment.class.getName(), budle);
fragments.add(f);
}
pagerAdapter = new PagerAdapter(super.getSupportFragmentManager(), fragments);
viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(pagerAdapter);
viewPager.setOnPageChangeListener(this);
} @Override
public void onPageScrolled(int i, float v, int i2) { } @Override
public void onPageSelected(int i) {
this.tabHost.setCurrentTab(i);
} @Override
public void onPageScrollStateChanged(int i) { } private void initTabHost(Bundle args) {
tabHost = (TabHost) findViewById(android.R.id.tabhost);
tabHost.setup();//初始化tabhost
TabInfo tabInfo = null;
for (int i = 0; i < 12; i++) {
TabHost.TabSpec tabSpec = this.tabHost.newTabSpec("Tab" + i);
tabSpec.setContent(new TabFactory(this));
View tabView = LayoutInflater.from(tabHost.getContext()).inflate(R.layout.tab_layout, null);
//获得本地图片路径
int resID = getResources().getIdentifier("a" + (i + 1) + "_0", "drawable", getPackageName());
((ImageView) tabView.findViewById(R.id.on)).setImageDrawable(getResources().getDrawable(resID)); resID = getResources().getIdentifier("a" + (i + 1) + "_1", "drawable", getPackageName());
((ImageView) tabView.findViewById(R.id.off)).setImageDrawable(getResources().getDrawable(resID)); //设置每一页spec显示的view
tabSpec.setIndicator(tabView);
tabHost.addTab(tabSpec);
tabInfo = new TabInfo("Tab" + i, HoroscopeFragment.class, args);
tabInfo.On = (ImageView) tabView.findViewById(R.id.on);
tabInfo.Off = (ImageView) tabView.findViewById(R.id.off);
tabInfo.Tab = tabView;
this.mapTabInfo.put(tabInfo.tag, tabInfo); //默认第一张显示的标签页
this.onTabChanged("Tab0");
tabHost.setOnTabChangedListener(this);
} } @Override
public void onTabChanged(String tabId) {
TabInfo newTab = this.mapTabInfo.get(tabId);
for (Map.Entry<String, TabInfo> t : mapTabInfo.entrySet()) {
if (t.getKey().equals(tabId)) {
t.getValue().On.setVisibility(View.VISIBLE);
t.getValue().Off.setVisibility(View.INVISIBLE);
} else {
t.getValue().On.setVisibility(View.INVISIBLE);
t.getValue().Off.setVisibility(View.VISIBLE);
}
} hScrollView.requestChildRectangleOnScreen(newTab.Tab, new Rect(0, 0, newTab.Tab.getWidth(), 1), false); int pos = this.tabHost.getCurrentTab();
this.viewPager.setCurrentItem(pos, true);
} public class PagerAdapter extends FragmentPagerAdapter { private List<android.support.v4.app.Fragment> fragments; public PagerAdapter(android.support.v4.app.FragmentManager fm, List<android.support.v4.app.Fragment> fragments) {
super(fm);
this.fragments = fragments;
} @Override
public android.support.v4.app.Fragment getItem(int position) {
return this.fragments.get(position);
} @Override
public int getCount() {
return this.fragments.size();
}
} }

HoroscaopeFragment.java

public class HoroscopeFragment extends Fragment {

    /**
*
* @param inflater 布局
* @param container 容器
* @param savedInstanceState
* @return view
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//i是Key后面的数字,实例化fragment后返回的参数
int i = getArguments().getInt("i") + 1;
//设置View的布局
final View view = inflater.inflate(R.layout.fragment_main,container,false);
/**
* 该方法用以异步获取在服务器配置的文字项内容,并设置为textView的文本,
* 如获取失败,textView的文本会设置为defaultValue。
* 详情见http://www.duducat.com/?article-doc.html
*/
ActiveConfig.setTextViewWithKey("Key"+i,null,(TextView)view.findViewById(R.id.content));
ActiveConfig.setImageViewWithKey("Key" + i,null,(ImageView)view.findViewById(R.id.cover));
ActiveConfig.getImageAsync("Key" + i,new ActiveConfig.AsyncGetImageHandler() {
/**
* 异步获取图片,成功设置显示
* @param drawable
*/
@Override
public void OnSuccess(Drawable drawable) {
((ImageView) view.findViewById(R.id.cover)).setImageDrawable(drawable);
view.findViewById(R.id.loading).setVisibility(View.INVISIBLE);
} @Override
public void OnFailed() { }
}); view.findViewById(R.id.content).setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
ActiveConfig.clearCache();
return true;
}
}); return view;
} }

ResizableImageView.java

public class ResizableImageView extends ImageView {
public ResizableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
} /**
* onMeasure来设置我们的视图的大小,但还有一个疑惑的地方,
* EXACTLY,AT_MOST,UNSPECIFIED和layout_是如何对应的呢?什么情况下对应什么值呢?
* MATCH_PARENT对应于EXACTLY,WRAP_CONTENT对应于AT_MOST,
* 其他情况也对应于EXACTLY,它和MATCH_PARENT的区别在于size值不一样。
*
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable d = getDrawable();
if(d != null){
// MeasureSpec.getSize(widthMeasureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)
int width = MeasureSpec.getSize(widthMeasureSpec);
//Math.ceil() 得到不小于他的最小整数
//获取Drawable d 对象的大小d.getIntrinsicHeight(),d.getIntrinsicWidth()
int height = (int)Math.ceil((float) width * (float)d.getIntrinsicHeight() / d.getIntrinsicWidth());
//设置自定义View的大小。详细描述见:http://blog.csdn.net/pi9nc/article/details/18764863
setMeasuredDimension(width,height); }
else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}

activtiy_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <TabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <!-- android:fillViewport=\"true\" 什么意思
ScrollView里只放一个元素.
当ScrollView里的元素想填满ScrollView时,使用"fill_parent"是不管用的,必需为ScrollView设置:
android:fillViewport="true".
当ScrollView没有fillVeewport=“true”时,里面的元素(比如LinearLayout)会按照wrap_content来计算
(不论它是否设了"fill_parent"),而如果LinearLayout的元素设置了fill_parent,那么也是不管用的,
因为LinearLayout依赖里面的元素,而里面的元素又依赖LinearLayout,这样自相矛盾.
所以里面元素设置了fill_parent,也会当做wrap_content来计算.
-->
<HorizontalScrollView
android:id="@+id/hScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/header_bg"
android:fillViewport="true"> <!-- android:tabStripEnabled="false" 不在选项卡绘制-->
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:tabStripEnabled="false"> </TabWidget> </HorizontalScrollView> <FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
/>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</TabHost> </LinearLayout>

fragment_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/content_bg"> <FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.jingling.practice.horoscope.ResizableImageView
android:id="@+id/cover"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:visibility="visible"/>
<ProgressBar
android:id="@+id/loading"
style="?android:attr/progressBarStyleLarge"
android:layout_width="100dp"
android:layout_height="150dp"
android:layout_gravity="center"
android:indeterminate="true"
android:paddingTop="50dp" />
</FrameLayout> <ScrollView
android:id="@+id/scrollView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="20dp" > <TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingMultiplier="1.5"
android:singleLine="false"
android:textColor="#ffffffff" />
</ScrollView>
</LinearLayout>

tab_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/on"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="matrix"
android:src="@drawable/a10_0"
android:visibility="invisible" /> <ImageView
android:id="@+id/off"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="matrix"
android:src="@drawable/a10_1"
android:visibility="visible" /> </FrameLayout>

源码已经上传至:https://github.com/presCheng/horoscope

星座物语APP的更多相关文章

  1. UESTC_秋实大哥の恋爱物语 2015 UESTC Training for Search Algorithm & String<Problem K>

    K - 秋实大哥の恋爱物语 Time Limit: 5000/2000MS (Java/Others)     Memory Limit: 32000/32000KB (Java/Others) Su ...

  2. 怪奇物语第二季/全集Stranger Things迅雷下载

    Netflix的叫好叫座剧<怪奇物语 Stranger Things>第二季更新上线日期为美国时间10月27日,第二季讲述在1984年(相隔上季一年),印第安纳州的Hawkins镇市民仍然 ...

  3. 2015 UESTC 搜索专题K题 秋实大哥の恋爱物语 kmp

    秋实大哥の恋爱物语 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/61 De ...

  4. cdoj1091-秋实大哥の恋爱物语 【kmp】

    http://acm.uestc.edu.cn/#/problem/show/1091 秋实大哥の恋爱物语 Time Limit: 5000/2000MS (Java/Others)     Memo ...

  5. FZU 2234 牧场物语【多线程dp】

     Problem 2234 牧场物语  Problem Description 小茗同学正在玩牧场物语.该游戏的地图可看成一个边长为n的正方形. 小茗同学突然心血来潮要去砍树,然而,斧头在小茗的右下方 ...

  6. 得物(毒)APP,8位抽奖码需求,这不就是产品给我留的数学作业!

    作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ...

  7. FZU2234 牧场物语 DP

    题意:先去再回,不能吃重复的,获取最大值 分析:等价于两个人同时去,不能吃重复的 定义dp[i][j][k]表示从起点走k步,第一个人的横坐标是i,第二个人的横坐标是j的最最大值 这个题和bc上一个回 ...

  8. 一步一步搞懂支持向量机——从牧场物语到SVM(上)

    之前在数据挖掘课程上写了篇关于SVM的"科普文",尽量通俗地介绍了SVM的原理和对各公式的理解.最近给正在初学机器学习的小白室友看了一遍,他觉得"很好,看得很舒服&quo ...

  9. NOIP2016——大家一起实现の物语

    由于最近硬盘挂了,换了个固态硬盘,比赛结束后四天一直在装Linux,所以最近一直没怎么更新 看起来挺漂亮的 比赛前一个月申请停了一个月晚自习,在我们这座城市里能做到这种事情已经可以被称为奇迹了,并且在 ...

随机推荐

  1. ASP.NET中Request.ApplicationPath、Request.FilePath、Request.Path、.Request.MapPath

    1.Request.ApplicationPath->当前应用的目录 2.Request.FilePath->对应于iis的虚拟目录   如 URL http://mockte.com/1 ...

  2. Java ClassLoader基础及加载不同依赖 Jar 中的公共类(转)

    http://www.iteye.com/topic/1135259 http://www.trinea.cn/android/java-loader-common-class/ http://www ...

  3. C# 实现文件或目录复制到指定目录

    public void CopyFilesToDirKeepSrcDirName(string srcPath, string destDir) { if (Directory.Exists(srcP ...

  4. 创建一个Android工程

    Creating an Android Project 原文演示了怎么通过Android Studio和命令行两种方式来创建一个Android工程. 原文链接:http://developer.and ...

  5. 本地apt

    Ubuntu建立本地源非常實用,很多服務器在局域網沒有網络或者網络很慢的情況下,或者需要批量安裝同样的軟件的時候,如果每一台服務器都去外網下載,是不是很慢,而且也不是一個運維工程師願意這麼幹的!那有什 ...

  6. cloudCompute

    云计算使企业可以迅速对市场做出反应而且加强了企业内部的协同 人人都在用云计算的时候能够迅速迁移到云平台已经不叫优势了,反而不使用云计算成为了一种劣势

  7. 港股street和nominee区别

    股票的street和nominee区别主要用在公司行动的过户费方面,street股票需要收取过户费,nominee不收过户费. street股票通过做公司行动收取过户费后会变成nominee股票,下次 ...

  8. 转: LRU缓存介绍与实现 (Java)

    引子: 我们平时总会有一个电话本记录所有朋友的电话,但是,如果有朋友经常联系,那些朋友的电话号码不用翻电话本我们也能记住,但是,如果长时间没有联系了,要再次联系那位朋友的时候,我们又不得不求助电话本, ...

  9. java笔记8之选择结构IF

    注意1 A比较表达式无论简单还是复杂,结果必须是boolean类型        B:if语句控制的语句体如果是一条语句,大括号可以省略:          如果是多条语句,就不能省略.建议永远不要省 ...

  10. 从APP消息推送所理解的观察者模式

    #1.什么是观察者模式? 观察者模式=(出版者+订阅者)模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能 ...