Android典型界面設計——ViewPage+Fragment實現區域頂部tab滑動切換


一、問題描述

  本系列將結合案例應用,陸續向大家介紹一些Android典型界面的設計,首先說說tab導航,導航分為一層和兩層(底部區塊+區域內頭部導航),主要實現方案有RadioGroup+ViewPage+Fragment、Viewpager Indicator、ActionBar Tabs、FragmentTabHost+Fragment等,下面我們先采用RadioGroup+ViewPage+Fragment實現區域頭部導航。

  如圖所示:

二、案例主要組件

  1、先看一下MainActivity布局

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
      <HorizontalScrollView
        android:id="@+id/hvChannel"
         android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none"
        >
        <RadioGroup
         android:id="@+id/rgChannel"
         android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:orientation="horizontal">
            
        </RadioGroup> 
    </HorizontalScrollView>
      <android.support.v4.view.ViewPager
              android:id="@+id/vpNewsList"
               android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
          >
      </android.support.v4.view.ViewPager>
</LinearLayout>            

  2、MainActivity代碼:

public class MainActivity extends FragmentActivity implements OnPageChangeListener{
    private ViewPager viewPager;
    private RadioGroup rgChannel=null;
    private HorizontalScrollView hvChannel;
    private PageFragmentAdapter adapter=null;
    private List<Fragment> fragmentList=new ArrayList<Fragment>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    private void initView(){
        rgChannel=(RadioGroup)super.findViewById(R.id.rgChannel);
        viewPager=(ViewPager)super.findViewById(R.id.vpNewsList);
        hvChannel=(HorizontalScrollView)super.findViewById(R.id.hvChannel);
        rgChannel.setOnCheckedChangeListener(
                new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, 
                    int checkedId) {
                viewPager.setCurrentItem(checkedId);        
            }
        });
        viewPager.setOnPageChangeListener(this);
        initTab();//動態產生RadioButton
        initViewPager();
        rgChannel.check(0);
    }
    private void initTab(){
        List<Channel> channelList=ChannelDb.getSelectedChannel();
        for(int i=0;i<channelList.size();i++){
            RadioButton rb=(RadioButton)LayoutInflater.from(this).
                    inflate(R.layout.tab_rb, null);
            rb.setId(i);
            rb.setText(channelList.get(i).getName());
            RadioGroup.LayoutParams params=new 
            RadioGroup.LayoutParams(RadioGroup.LayoutParams.WRAP_CONTENT,
                            RadioGroup.LayoutParams.WRAP_CONTENT);
            rgChannel.addView(rb,params);
        }
        
    }
    private void initViewPager(){
        List<Channel> channelList=ChannelDb.getSelectedChannel();
        for(int i=0;i<channelList.size();i++){
            NewsFragment frag=new NewsFragment();
            Bundle bundle=new Bundle();
            bundle.putString("weburl", channelList.get(i).getWeburl());
            bundle.putString("name", channelList.get(i).getName());
            frag.setArguments(bundle);     //向Fragment傳入數據
            fragmentList.add(frag);
        }
        adapter=new PageFragmentAdapter(super.getSupportFragmentManager(),fragmentList);
        viewPager.setAdapter(adapter);
        //viewPager.setOffscreenPageLimit(0);
    }
    
    /**
     * 滑動ViewPager時調整ScroollView的位置以便顯示按鈕
     * @param idx
     */
    private void setTab(int idx){
        RadioButton rb=(RadioButton)rgChannel.getChildAt(idx);
        rb.setChecked(true);
        int left=rb.getLeft();
        int width=rb.getMeasuredWidth();
        DisplayMetrics metrics=new DisplayMetrics();
        super.getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int screenWidth=metrics.widthPixels;
        int len=left+width/2-screenWidth/2;
        hvChannel.smoothScrollTo(len, 0);//滑動ScroollView
    }
    @Override
    public void onPageScrollStateChanged(int arg0) {
    
    }
    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {

    }
    @Override
    public void onPageSelected(int position) {
        // TODO Auto-generated method stub
        setTab(position);
    }
}

  其中initTab()方法實現向RadioGroup動態添加RadioButton

  導航按鈕數據來源於ChannelDb

    private static List<Channel>   selectedChannel=new ArrayList<Channel>();
    static{
        selectedChannel.add(new Channel("","頭條",0,"",""));
        selectedChannel.add(new Channel("","娛樂",0,"",""));
        selectedChannel.add(new Channel("","體育",0,"",""));
        selectedChannel.add(new Channel("","財經",0,"",""));
        selectedChannel.add(new Channel("","熱點",0,"",""));
        selectedChannel.add(new Channel("","科技",0,"",""));
        selectedChannel.add(new Channel("","圖片",0,"",""));
        selectedChannel.add(new Channel("","汽車",0,"",""));
        selectedChannel.add(new Channel("","時尚",0,"",""));
    }
    public static  List<Channel> getSelectedChannel(){
         return selectedChannel;
    }

  導航按鈕外觀:tab_rb.xml和tab_selector.xml背景選擇器(實現選擇后帶紅色下划線效果)

<?xml version="1.0" encoding="utf-8"?>
<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="wrap_content"
                android:layout_height="30dp"
                android:text="今日"
                android:background="@drawable/tab_selector"
                android:paddingLeft="15dp"
                android:paddingRight="15dp"
                 android:paddingTop="10dp"
                android:paddingBottom="10dp"
                  android:button="@null"
                />

tab_selector.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
      <item android:state_checked="true" ><!-- 選中狀態 -->
        <layer-list >
            <item >
                <shape android:shape="rectangle">
                    <stroke android:width="5dp"  android:color="#ff0000"/>    
                </shape>
            </item>
            <item  android:bottom="5dp" >
                <shape android:shape="rectangle" >
                        <solid android:color="#fff"/>
               </shape>
            </item>
        </layer-list> 
    </item>
    <item ><!-- 默認狀態 -->
        <shape >
                <solid  android:color="#FAFAFA"/>
        </shape>
    </item>
</selector>

3、PageFragmentAdapter適配器

public class PageFragmentAdapter extends FragmentPagerAdapter{
    private List<Fragment> fragmentList;
    private FragmentManager fm;
    public PageFragmentAdapter(FragmentManager fm,List<Fragment> fragmentList){
        super(fm);
        this.fragmentList=fragmentList;
        this.fm=fm;
    }
    @Override
    public Fragment getItem(int idx) {
        return fragmentList.get(idx%fragmentList.size());
    }
    @Override
    public int getCount() {
        return fragmentList.size();
    }
    @Override  
    public int getItemPosition(Object object) {  
       return POSITION_NONE;  //沒有找到child要求重新加載
    }  }

4、NewsFragment組件:

public class NewsFragment extends Fragment {
    private String weburl;
    private String channelName;
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
    }
    private View view;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if(view==null){//優化View減少View的創建次數    
            //該部分可通過xml文件設計Fragment界面,再通過LayoutInflater轉換為View組件
            //這里通過代碼為fragment添加一個TextView
            TextView tvTitle=new TextView(getActivity());
            tvTitle.setText(channelName);
            tvTitle.setTextSize(16);
            tvTitle.setGravity(Gravity.CENTER);
            tvTitle.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
            view=tvTitle;
        }
        ViewGroup parent=(ViewGroup)view.getParent();
        if(parent!=null){//如果View已經添加到容器中,要進行刪除,負責會報錯
            parent.removeView(view);
        }
        return view;
    }
    @Override
    public void setArguments(Bundle bundle) {//接收傳入的數據
        weburl=bundle.getString("weburl");
        channelName=bundle.getString("name");    
    }
    
}

 

  想要了解更多內容的小伙伴,可以點擊查看源碼,親自運行測試。

  疑問咨詢或技術交流,請加入官方QQ群:JRedu技術交流 (452379712)

作者: 傑瑞教育
出處: http://www.cnblogs.com/jerehedu/ 
本文版權歸煙台傑瑞教育科技有限公司和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM