效果图:

    

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