效果图:

    

这里的后台管理用的是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. Gnuradio 学习

    8月份就把usrp买过来了,不过由于一直比较忙, 也没怎么弄. 这几天准备学习学习,暂时也不知道能干些啥.不管怎么样先按教程走一遍,熟悉熟悉设备也是好的吧. 首先去Ettus 下载了一个官方指导,一步 ...

  2. UVa 10020 - Minimal coverage(区间覆盖并贪心)

    Given several segments of line (int the X axis) with coordinates [Li, Ri]. You are to choose the min ...

  3. iOS 写入文件保存数据的方式

     在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好.下面介绍一下数据保存的方式: 1.NSKeye ...

  4. 【Java】环境变量的配置

    注意点 1.环境变量不能有空格,比如C:\Program Files 2.JAVA_HOME:D:\Java\jdk1.7.0_67------------->注意不能加;分号

  5. C获取本地时间的localtime函数

    最近有朋友问如下问题: #include <stdio.h>#include <stdlib.h>#include <iconv.h>#include <ti ...

  6. BAT之间的区别(学点网页编程,然后开始研究)

    A: 阿里不就是靠网页起家的吗? T: 腾讯靠客户端. B: 百度是靠网页背后的算法技术支持- 最近网页技术又发布了很多新功能,而现在网页功能也已经很强大了. 不知道自己是不是老了,总觉得不喜欢网页( ...

  7. linux wenjian

    文件锁是一种文件读写机制,在任何特定的时间只允许一个进程访问一个文件.利用这种机制能够使读写单个文件的过程变得更安全. 在这篇文章中,我们将探讨Linux中不同类型的文件锁,并通过示例程序来理解它们之 ...

  8. java 上传图片 打水印

    其实就是在现有的图片上,画东西,也可以直接 贴图片 //添加水印 @Override public File pressFile(File file,String press_path) throws ...

  9. Delphi HTTP error message: Can't execute C:\Program Files\Borland\Delphi7\Bin\serverinfo.exe 1813

    delphi  调用Webservice ,停止服务的时候总是爱提示: Internal Server ErrorHTTP status code: 500 HTTP error message: C ...

  10. Tomcat启动时报错:java.net.BindException: Permission denied <null>:80 【转载】

    本文转载自: http://blog.sina.com.cn/s/blog_4550f3ca0101g37l.html   问题起因:做负载均衡时需要将Web工程与Wap工程同时部署在一台Suse服务 ...