• Android应用经典主界面框架之二:仿网易新闻client、CSDN client (Fragment ViewPager)


    另外一种主界面风格则是以网易新闻、凤凰新闻以及新推出的新浪博客(阅读版)为代表,使用ViewPager+Fragment。即ViewPager里适配器里放的不是一般的View。而是Fragment。所以适配器不能继承PagerAdapter,而要继承FragmentPagerAdapter,这是在android.support.v4.app.FragmentPagerAdapter包里的。有点奇葩的是,FragmentPagerAdapter仅仅在这个包里有,在android.app.*这个包以下么有。

    到后面会发现,仅仅能用android.support.v4.app.*包以下的东西。两个包里的FragmentManager是不通用的,并且两个包里提供的Fragment也不大一样。假设继承android.app.*下的Fragment,则不能又一次写构造函数,仅仅能用默认的。v4的包里么有这个限制。

    下图是网易新闻、凤凰新闻、新浪博客的截图:



    关于仿网易新闻client代码已经非常多了,本人主要依据开源的这个CSDNclient的制作。准备一步步搞下。这本是一个大牛之作发在oschina上,參考链接里分5步去实现。我看了它的代码,是染在一起的。比方要完这个导航不须要额外的三个包,而他的资源里是弄一起的。所以准备自己玩玩,顺便记录开发中的问题。

    第一步:最上面的导航栏

    即有“网易新闻”四个大字这一栏。布局文件head_title_panel.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="wrap_content"
        android:background="@color/light_blue"
        android:orientation="horizontal" >
    
        <ImageView
            android:id="@+id/headIcon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="4dp"
            android:src="@drawable/biz_navigation_tab_news_pressed" />
    
        <ImageView
            android:id="@+id/headDivider"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:src="@drawable/base_action_bar_back_divider" />
    
        <TextView
            android:id="@+id/headTV"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="4dp"
            android:layout_weight="1"
            android:text="CSDN资讯"
            android:textColor="@color/white"
            android:textSize="21sp"
            android:textStyle="bold">
        </TextView>
    
    
    </LinearLayout>
    为了日后操作上的方便,我将它映射成一个HeadTitlePanel.java文件。能够看到这样的写法跟上篇 上下panel的定义是有点差别的。

    package org.yanzi.ui;
    
    import org.yanzi.csdnproject.R;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    
    public class HeadTitlePanel extends RelativeLayout {
    
    	private Context mContext;
    	private TextView mHeadTV;
    	private ImageView mHeadIcon;
    	private ImageView mHeadDivider;
    	
    	public HeadTitlePanel(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		// TODO Auto-generated constructor stub
    		mContext = context;
    		View parent = LayoutInflater.from(mContext).inflate(R.layout.head_title_panel, this, true);
    		mHeadTV = (TextView) parent.findViewById(R.id.headTV);
    	}
    
    	
    
    }
    

    第二步:ViewPager的导航栏

    这个本来我是准备自己封装个的,网上也实用Radiobutton封装的,考虑到它这个导航栏还是不固定长度能够滑动的,时间原因临时不封装了。使用开源Android-ViewPagerIndicator-master.zip 这个包。这个人的github链接:https://github.com/JakeWharton 将当中的library目录改名ViewPagerIndicator_library导进来。这个里面有好几种Indicator。我们主要用TabPageIndicator这个。

    第三步:MainActivity的布局:

    activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#eee"
        tools:context=".MainActivity" >
    
        <org.yanzi.ui.HeadTitlePanel
            android:id="@+id/head_title_panel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true" />
    
        <com.viewpagerindicator.TabPageIndicator
            android:id="@+id/page_indicator"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/head_title_panel"
            android:background="@color/transparentblue" />
    
        <android.support.v4.view.ViewPager
            android:id="@+id/view_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/page_indicator"
           />
    
    </RelativeLayout>
    MainActivity.java

    package org.yanzi.csdnproject;
    
    import org.yanzi.viewpager.adapter.TabAdapter;
    
    import com.viewpagerindicator.TabPageIndicator;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.app.FragmentManager;
    import android.view.Menu;
    import android.support.v4.app.FragmentActivity;
    import android.support.v4.app.FragmentPagerAdapter;
    import android.support.v4.view.ViewPager;
    
    public class MainActivity extends FragmentActivity {
    private TabPageIndicator mPageIndicator;
    private ViewPager mViewPager;
    private FragmentPagerAdapter fragPagerAdapter;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		initUI();
    		
    		fragPagerAdapter = new TabAdapter(getSupportFragmentManager());
    		mViewPager.setAdapter(fragPagerAdapter);
    		mPageIndicator.setViewPager(mViewPager, 0);
    		
    		
    	}
    
    	@Override
    	public boolean onCreateOptionsMenu(Menu menu) {
    		// Inflate the menu; this adds items to the action bar if it is present.
    		getMenuInflater().inflate(R.menu.main, menu);
    		return true;
    	}
    	private void initUI(){
    		mPageIndicator = (TabPageIndicator)findViewById(R.id.page_indicator);
    		mViewPager = (ViewPager)findViewById(R.id.view_pager);
    	}
    
    }
    

    出奇的简单,比单纯用Fragment还简单,原因是仅仅需把Fragment塞到适配器里就ok了。适配器为我们做了Fragment的切换等工作。我们能做的也就是在适配器里new Fragment的时候推断是否已存在。以下几点须要注意:

    1、在styles.xml里它定义了样式:

        <style name="MyTheme" parent="AppBaseTheme">
            <item name="vpiTabPageIndicatorStyle">@style/MyWidget.TabPageIndicator</item>
            <item name="android:windowBackground">@drawable/init_pic</item>
            <item name="android:windowNoTitle">true</item>
            <item name="android:animationDuration">5000</item>
            <item name="android:windowContentOverlay">@null</item>
        </style>
        <style name="MyWidget.TabPageIndicator" parent="Widget">
            <item name="android:gravity">center</item>
            <item name="android:background">@drawable/vpi__tab_indicator</item>
            <item name="android:paddingLeft">22dip</item>
            <item name="android:paddingRight">22dip</item>
            <item name="android:paddingTop">8dp</item>
            <item name="android:paddingBottom">8dp</item>
            <item name="android:textAppearance">@style/MyTextAppearance.TabPageIndicator</item>
            <item name="android:textSize">16sp</item>
            <item name="android:maxLines">1</item>
        </style>
    
        <style name="MyTextAppearance.TabPageIndicator" parent="Widget">
            <item name="android:textStyle">bold</item>
            <item name="android:textColor">@color/black</item>
        </style>

    这个是依赖于导进去的包的。

    2、它这里用了android:windowBackground的属性,所以app开启瞬间会有图片弹出,之后设置MainActivity的布局背景为android:background="#eee",又把图片替换了。假设不设android:background="#eee" 会一直看到这个图片不消失。

    3、由于开篇讲的原因,MainActivity仅仅能继承自FragmentActivity。

    第四步:MainFragment.java,此类继承Fragment。且是android.support.v4.app.Fragment下的。

    package org.yanzi.fragment;
    
    import org.yanzi.csdnproject.R;
    
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    
    public class MainFragment extends Fragment {
    	private int mNewsType = 0;
    
    	@Override
    	public View onCreateView(LayoutInflater inflater, ViewGroup container,
    			Bundle savedInstanceState) {
    		// TODO Auto-generated method stub
    		View v = inflater.inflate(R.layout.tab_item_fragment_main, null);
    		TextView tip = (TextView) v.findViewById(R.id.id_tip);
    		Bundle b = getArguments();
    		String title = b.getString("TITLES");
    		tip.setText(title);
    		return v;
    	}
    	@Override
    	public void onActivityCreated(Bundle savedInstanceState) {
    		// TODO Auto-generated method stub
    		super.onActivityCreated(savedInstanceState);
    	}
    	
    
    }
    
    就是弄了一个布局。然后从中取得參数并显示。

    第五步:ViewPager的适配器TabAdapter.java

    package org.yanzi.viewpager.adapter;
    
    import org.yanzi.constant.Constant;
    import org.yanzi.fragment.MainFragment;
    
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentPagerAdapter;
    
    public class TabAdapter extends FragmentPagerAdapter {
    
    	public TabAdapter(FragmentManager fm) {
    		
    		super(fm);
    		// TODO Auto-generated constructor stub
    	}
    
    	@Override
    	public Fragment getItem(int position) {
    		// TODO Auto-generated method stub
    		MainFragment fragment = new MainFragment();
    		Bundle b = new Bundle();
    		String title = Constant.TITLES[position];
    		b.putString("TITLES", title);
    		fragment.setArguments(b);
    		return fragment;
    	}
    
    	@Override
    	public CharSequence getPageTitle(int position) {
    		// TODO Auto-generated method stub
    		return Constant.TITLES[position];
    	}
    
    	@Override
    	public int getCount() {
    		// TODO Auto-generated method stub
    		return Constant.TITLES.length;
    	}
    
    }
    

    主要是重写getItem,在这里实例化Fragment,同一时候设传递的參数。

    事实上这里能够通过

    FragmentManager
    依照Tag查找相应的Fragment是否存在,再进行实例化。

    另外,getPageTitle这个接口必须重写,事实上看TabPageIndicator.java这个类的实现能够发现。它须要传进去一个ViewPager,然后获得适配器,从适配器里得到Title。由于用了这个开源包,不能再用ViewPager的setOnPageChangeListener接口,仅仅能用mPageIndicator.setOnPageChangeListener(listener)进行监听。

    完成,源代码链接:链接:http://pan.baidu.com/s/1bn4EFbp password:dx4s

    效果例如以下:






  • 相关阅读:
    使用python3自带工具2to3.py 转换 python2.x 代码 到python3
    python2代码转换python3(2018新)
    解析搜狗词库(python)
    把搜狗输入法词库导入Google拼音输入法
    QT 窗体控件的透明度设置(三种方法)
    Telnet协议详解(远程登陆协议)
    C++游戏开发需要阅读的书籍
    explicit的作用
    C#7.0
    ES6-2
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/6944730.html
Copyright © 2020-2023  润新知