效果图:
这里的后台管理用的是duducat,大家可以去百度看说明。图片,文字都在duducat后台服务器上,可以自己修改的。(PS:图片这里是随便找的)
我就直接上代码了,如果有不懂的可以联系我。
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>