星座物语APP

效果图:

    

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

时间: 2024-10-29 19:11:51

星座物语APP的相关文章

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

http://acm.uestc.edu.cn/#/problem/show/1091 秋实大哥の恋爱物语 Time Limit: 5000/2000MS (Java/Others)     Memory Limit: 32000/32000KB (Java/Others) Submit Status 传说有这么一个故事! 在一个月白风清的晚上,秋实大哥约一位他心仪的妹子一起逛校园,浪漫的秋实大哥决定在当晚对妹子表白.“XXXXX...”,秋实大哥温情地说完了准备已久的话.而妹子决定用一种浪漫的

UESTC_秋实大哥の恋爱物语 2015 UESTC Training for Search Algorithm &amp; String&lt;Problem K&gt;

K - 秋实大哥の恋爱物语 Time Limit: 5000/2000MS (Java/Others)     Memory Limit: 32000/32000KB (Java/Others) Submit Status 传说有这么一个故事! 在一个月白风清的晚上,秋实大哥约一位他心仪的妹子一起逛校园,浪漫的秋实大哥决定在当晚对妹子表白.“XXXXX...”,秋实大哥温情地说完了准备已久的话.而妹子决定用一种浪漫的方式接受秋实大哥(其实妹子早已对秋实大哥动心,这一刻她早已迫不及待了,但还是决定

侠物语破解算法

private function decode(data:ByteArray):ByteArray{ var dest:ByteArray = new ByteArray(); var index:int; var key:String = "I'm a big big girl with a big big hole"; var count:int; var i:int; while (i < data.length) { if (index>= key.length){

[从头读历史] 第295节 神之物语 结语:为什么会有希腊神话

剧情提要: 为什么会有希腊神话,因为一个文明需要记录它的历史,而希腊历史很不幸地因为 断代原因,造成了明知道存在爱琴文明,却丧失了所有记录的境地,这个补全历史 的艰巨任务,就落到了史诗作者的肩头,所以,选择编造神话是唯一的解决途径. 正剧开始: 星历2016年07月09日 15:56:17, 银河系厄尔斯星球中华帝国江南行省. [工程师阿伟]正在和[机器小伟]一起研究[神之物语 为什么会有希腊神话]. 古希腊神话人物名称和简介 宙斯(Zeus),天神,古希腊神话中最高的神,罗马神话中称朱庇特(J

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

 Problem 2234 牧场物语  Problem Description 小茗同学正在玩牧场物语.该游戏的地图可看成一个边长为n的正方形. 小茗同学突然心血来潮要去砍树,然而,斧头在小茗的右下方. 小茗是个讲究效率的人,所以他会以最短路程走到右下角,然后再返回到左上角.并且在路上都会捡到/踩到一些物品,比如说花朵,钱和大便等. 物品只能被取最多一次.位于某个格子时,如果格子上还有物品,就一定要取走.起点和终点上也可能有物品. 每种物品我们将为其定义一个价值,当然往返之后我们取得的物品的价值

双线dp ——牧场物语

牧场物语 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice FZU 2234 Description 小茗同学正在玩牧场物语.该游戏的地图可看成一个边长为n的正方形. 小茗同学突然心血来潮要去砍树,然而,斧头在小茗的右下方. 小茗是个讲究效率的人,所以他会以最短路程走到右下角,然后再返回到左上角.并且在路上都会捡到/踩到一些物品,比如说花朵,钱和大

微信之初学者:列表方法之洪荒物语

1.append(用于在列表末尾追加新的对象) lst = [1,2,3,4] lst.append(5) print(lst) 2.count(统计某个元素在列表出现的次数) y = ['a','v','da','asd','w','gg'] print(y.count('da')) x = [[1,2],1,1,2,[1,1],] print(x.count(1)) print(x.count([1,2]))#列表里的元素也可以是列表 3.extend(在列表的末尾一次性追加另一个序列中的某

微信之初学者:列表方法之蛮荒物语

1.pop(移除列表中的一个元素,默认是最后一个,病返回该元素的值,除了None) x = [1,2,3,4] a = x.pop() b = x.pop(1)#可以指定移除元素 print(a,b) 2.remove(移除列表中某个之的第一个匹配项) x = [1,2,3,4,5,3] x.remove(3)#不会返回元素值 print(x) x.remove(2) print(x) 3.reverve(将列表里的元素反向存放) x = [1,2,3,4,5] x.reverse()#也不会返

UESTC 1091秋实大哥の恋爱物语 [偏移模式匹配]

题目链接:http://acm.uestc.edu.cn/#/problem/show/1091 题目大意:求模式串p,在s中出现的次数,但是p能平移到s即可,比如s: 1 3 4和 p :0 2 3: 题目思路:处理出每一位相对前一位的变化,然后KMP即可: 代码: //author:ACsorry //result:Yes #include<iostream> #include<cstdio> #include<cstring> #include<cmath&