조각 예 - 하단 탐색 모음 + 페이지 전환을 위한 ViewPager 슬라이딩


처음 세 섹션에서는 일반 하단 네비게이션 바의 효과를 다양한 방식으로 구현했으며, 이번 섹션에서는 다음을 기반으로 두 번째 예시를 사용하겠습니다. 페이지 전환 슬라이딩 효과를 얻으려면 ViewPager를 추가하세요! 내 친구들 대부분은 이 ViewPager가 무엇인지 알고 있습니다. 모르셔도 상관없습니다. 이 컨트롤에 대해 간단히 소개하겠습니다!


1. ViewPager에 대한 간략한 소개


1) 어떤 컨트롤인가요?

답변: 페이지 전환 구성요소로, 이를 여러 보기로 채울 수 있으며 화면을 터치하여 왼쪽과 오른쪽으로 슬라이드할 수 있습니다. 서로 다른 뷰 사이를 전환하는 것은 앞서 배운 ListView와 동일합니다. 표시할 뷰를 결합하려면 어댑터가 필요합니다. ViewPager는 바인딩되어 있으며 ViewPager에는 고유한 특정 Adapter-PagerAdapter가 있습니다! 게다가 구글은 공식적인 권장 사항은 각 페이지를 보다 편리하게 생성하고 관리할 수 있는 ViewPager를 채우기 위해 Fragment를 사용하는 것입니다. 각 페이지의 수명 주기는 물론 FragmentPageAdapterFragmentStatePagerAdapter라는 두 가지 어댑터를 제공합니다! 이 섹션에서 사용하는 것은 전자인 FragmentPageAdapter입니다! 언급할 또 다른 사항은 ViewPager의 캐싱 메커니즘입니다. ViewPager는 현재 페이지, 이전 페이지 및 다음 페이지를 캐시합니다. 예를 들어 1, 2, 3, 4개의 페이지가 있습니다. 첫 번째 페이지에 있을 때: Cache 1, 2
——> 두 번째 페이지에 있을 때: Cache 1, 2, 3
——> 세 번째 페이지에 있을 때: Cache 2, 3, 4 ——> 4페이지 캐시 3, 4에 이렇게 나와있어요!

2) PagerAdapter를 사용하여 관련 메소드를 다시 작성합니다.

  • getCount( ): 뷰페이지에 있는 뷰 수를 가져옵니다.
  • destroyItem( ): 지정된 위치에서 페이지를 제거합니다. 컨테이너에서 이 뷰를 제거하는 것은 어댑터의 책임입니다. 이는 다음을 보장하기 위한 것입니다. FinishUpdate(viewGroup)가 반환되면 뷰가 제거될 수 있습니다.
  • instantiateItem( ): ① 주어진 위치의 뷰를 ViewGroup(컨테이너)에 추가하고 생성하여 표시합니다. ②새로 추가된 페이지를 나타내는 객체(키)를 반환합니다. 일반적으로 뷰 자체를 직접 반환합니다. 물론 자신만의 키를 맞춤설정할 수도 있지만 키와 각 뷰 사이에는 일대일 대응이 있어야 합니다
  • isViewFromObject( ): instantiateItem(ViewGroup, int) 함수에서 키를 반환하는지 여부를 확인합니다. 페이지 조회수와 동일합니다. 동일한 뷰를 나타냅니다(즉, 대응하는지, 대응하는 뷰가 동일한 뷰를 나타내는지 여부). 일반적으로 우리는 직접 작성합니다. return view == object; 그게 다입니다. 왜 이렇게 되었는지는 나중에 좀 더 자세히 알아볼 기회가 있을 것입니다. ViewPager에는 View 상태 정보를 저장하는 ArrayList가 있는 것 같습니다. View를 기반으로 해당 정보를 검색할 수 있습니다.

PS:모든 메소드를 다시 작성할 필요는 없습니다~


2. 및 프로젝트 디렉토리 구조:

먼저 달성하려는 효과를 살펴보겠습니다

1.gif

프로젝트 구조를 살펴보겠습니다:

2.png


3. 코드 구현:


1단계: 관련 리소스 파일 준비:

PS: 하단 탐색 모음 방법 2를 구현합니다. 기본을 바탕으로 작성되었으니 리소스 파일을 복사해두시면 됩니다! 여기에는 여러번 올리지 않겠습니다~!

2단계: Activity_main.xml의 레이아웃 파일 작성:

PS: 이전 FrameLayout을 android.support.v4.view.ViewPager:

activity_mian.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"
    tools:context=".MainActivity">

    <RelativeLayout
        android:id="@+id/ly_top_bar"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:background="../style/images/bg_topbar">

        <TextView
            android:id="@+id/txt_topbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:text="提醒"
            android:textColor="@color/text_topbar"
            android:textSize="18sp" />

        <View
            android:layout_width="match_parent"
            android:layout_height="2px"
            android:layout_alignParentBottom="true"
            android:background="../style/images/div_white" />

    </RelativeLayout>


    <RadioGroup
        android:id="@+id/rg_tab_bar"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:layout_alignParentBottom="true"
        android:background="../style/images/bg_white"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/rb_channel"
            style="@style/tab_menu_item"
            android:drawableTop="@drawable/tab_menu_channel"
            android:text="@string/tab_menu_alert" />

        <RadioButton
            android:id="@+id/rb_message"
            style="@style/tab_menu_item"
            android:drawableTop="@drawable/tab_menu_message"
            android:text="@string/tab_menu_profile" />

        <RadioButton
            android:id="@+id/rb_better"
            style="@style/tab_menu_item"
            android:drawableTop="@drawable/tab_menu_better"
            android:text="@string/tab_menu_pay" />

        <RadioButton
            android:id="@+id/rb_setting"
            style="@style/tab_menu_item"
            android:drawableTop="@drawable/tab_menu_setting"
            android:text="@string/tab_menu_setting" />

    </RadioGroup>

    <View
        android:id="@+id/div_tab_bar"
        android:layout_width="match_parent"
        android:layout_height="2px"
        android:layout_above="@id/rg_tab_bar"
        android:background="../style/images/div_white" />

    <android.support.v4.view.ViewPager
        android:id="@+id/vpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/div_tab_bar"
        android:layout_below="@id/ly_top_bar" />


</RelativeLayout>

3단계: 쓰기 조각의 레이아웃 및 코드:

PS: ViewPager의 메커니즘을 보여주기 위해 여기에는 4개의 조각이 특별히 작성되었습니다! 인쇄 생성 로그인 onCreateView!

fg_content.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:background="../style/images/bg_white"
    android:orientation="vertical">

    <TextView
        android:id="@+id/txt_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="呵呵"
        android:textColor="@color/text_yellow"
        android:textSize="20sp" />

</LinearLayout>

MyFragment1.java:

/**
 * Created by Jay on 2015/8/28 0028.
 */
public class MyFragment1 extends Fragment {

    public MyFragment1() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fg_content, container, false);
        TextView txt_content = (TextView) view.findViewById(R.id.txt_content);
        txt_content.setText("第一个Fragment");
        Log.e("HEHE", "1日狗");
        return view;
    }
}

나머지 3개는 조롱박과 똑같습니다. 하나만 바꾸세요!

4단계: FragmentPagerAdapter 클래스 사용자 정의:

코드는 매우 간단합니다. FragmentManager를 전달하기만 하면 다른 모든 작업이 여기서 완료됩니다!

/**
 * Created by Jay on 2015/8/31 0031.
 */
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    private final int PAGER_COUNT = 4;
    private MyFragment1 myFragment1 = null;
    private MyFragment2 myFragment2 = null;
    private MyFragment3 myFragment3 = null;
    private MyFragment4 myFragment4 = null;


    public MyFragmentPagerAdapter(FragmentManager fm) {
        super(fm);
        myFragment1 = new MyFragment1();
        myFragment2 = new MyFragment2();
        myFragment3 = new MyFragment3();
        myFragment4 = new MyFragment4();
    }


    @Override
    public int getCount() {
        return PAGER_COUNT;
    }

    @Override
    public Object instantiateItem(ViewGroup vg, int position) {
        return super.instantiateItem(vg, position);
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        System.out.println("position Destory" + position);
        super.destroyItem(container, position, object);
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;
        switch (position) {
            case MainActivity.PAGE_ONE:
                fragment = myFragment1;
                break;
            case MainActivity.PAGE_TWO:
                fragment = myFragment2;
                break;
            case MainActivity.PAGE_THREE:
                fragment = myFragment3;
                break;
            case MainActivity.PAGE_FOUR:
                fragment = myFragment4;
                break;
        }
        return fragment;
    }

}

5단계: MainActivity 작성:

논리는 매우 간단합니다. 직접 확인해 보세요~

MainActivity.java:

package com.jay.fragmentdemo4;

import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;


/**
 * Created by Coder-pig on 2015/8/28 0028.
 */
public class MainActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener,
        ViewPager.OnPageChangeListener {

    //UI Objects
    private TextView txt_topbar;
    private RadioGroup rg_tab_bar;
    private RadioButton rb_channel;
    private RadioButton rb_message;
    private RadioButton rb_better;
    private RadioButton rb_setting;
    private ViewPager vpager;

    private MyFragmentPagerAdapter mAdapter;

    //几个代表页面的常量
    public static final int PAGE_ONE = 0;
    public static final int PAGE_TWO = 1;
    public static final int PAGE_THREE = 2;
    public static final int PAGE_FOUR = 3;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
        bindViews();
        rb_channel.setChecked(true);
    }

    private void bindViews() {
        txt_topbar = (TextView) findViewById(R.id.txt_topbar);
        rg_tab_bar = (RadioGroup) findViewById(R.id.rg_tab_bar);
        rb_channel = (RadioButton) findViewById(R.id.rb_channel);
        rb_message = (RadioButton) findViewById(R.id.rb_message);
        rb_better = (RadioButton) findViewById(R.id.rb_better);
        rb_setting = (RadioButton) findViewById(R.id.rb_setting);
        rg_tab_bar.setOnCheckedChangeListener(this);

        vpager = (ViewPager) findViewById(R.id.vpager);
        vpager.setAdapter(mAdapter);
        vpager.setCurrentItem(0);
        vpager.addOnPageChangeListener(this);
    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        switch (checkedId) {
            case R.id.rb_channel:
                vpager.setCurrentItem(PAGE_ONE);
                break;
            case R.id.rb_message:
                vpager.setCurrentItem(PAGE_TWO);
                break;
            case R.id.rb_better:
                vpager.setCurrentItem(PAGE_THREE);
                break;
            case R.id.rb_setting:
                vpager.setCurrentItem(PAGE_FOUR);
                break;
        }
    }


    //重写ViewPager页面切换的处理方法
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    @Override
    public void onPageSelected(int position) {
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        //state的状态有三个,0表示什么都没做,1正在滑动,2滑动完毕
        if (state == 2) {
            switch (vpager.getCurrentItem()) {
                case PAGE_ONE:
                    rb_channel.setChecked(true);
                    break;
                case PAGE_TWO:
                    rb_message.setChecked(true);
                    break;
                case PAGE_THREE:
                    rb_better.setChecked(true);
                    break;
                case PAGE_FOUR:
                    rb_setting.setChecked(true);
                    break;
            }
        }
    }
}


PS: 헤헤, 위에 가이드 패키지 부분의 코드도 게시했습니다. , 잘못된 패키지를 가져오거나 설명할 수 없는 오류가 발생할까 두렵습니다! ViewPager는 v4 패키지에 속하므로 Fragment, FragmentManager 및 FragmentTransaction을 모두 사용해야 합니다. V4 패키지 아래에 있습니다! 또한 FragmentManager를 얻는 방법은 getFragmentManager()를 직접 사용하는 것이 아니라 getSupportFragmentManager() 오!

참고: ViewPager가 RadioButton 뒤에 배치되면 RadioButton의 클릭 이벤트가 유효하지 않습니다.


4. 코드 다운로드:

FragmentDemo4: Download FragmentDemo4.zip


이 섹션 요약:

자, 위는 간단한 슬라이딩을 구현하기 위한 하단 탐색 모음 + ViewPager의 구현 과정입니다. 조각 전환! 그게 다예요, 감사합니다~