Study notes ------------- pit encountered by viewpager2

Keywords: Android viewpager

Previous results:

There are two problems in this project:
1. State when ImageView uses mixed images_ The checked attribute setSelected(true) is invalid in the code. The specific reason is not found

So I used state_ This attribute is replaced by pressed

However, there was another problem. Pressing the button would change color. After releasing the button, it bounced back to the original color, so I changed the click event to touch event

In this way, the touch can directly capture the state.
2.text discoloration fails when setTextcolor(R.color.xxx) is used

The reason is that setTextcolor accepts hexadecimal data instead of resource id. if you want to use it, you need to call the getColor method

Well, don't say much. Let's start the text
·Add the viewpager2 control in the activity (the old sdk may need to add the corresponding control package in build.gradle)

·Prepare eight pictures( Alibaba vector icon library ), create four groups of picture resource files in drawable (click to change the picture background)

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/faxian_on"  android:state_pressed="true"/>
    <item android:drawable="@drawable/faxian"  />
</selector>

·Create navigation bar

<?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="horizontal">
    <LinearLayout
        android:id="@+id/weixin"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">
        //Add a mixed picture_ fix
        <ImageView
            android:id="@+id/weixin_button"
            android:layout_gravity="center_horizontal"
            android:background="@drawable/weixinliaotian_fix"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:text="WeChat"
            android:id="@+id/t1"
            android:layout_gravity="center_horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/tongxunlu"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/tongxunlu_button"
            android:layout_gravity="center_horizontal"
            android:background="@drawable/tongxunlu_fix"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/t2"
            android:layout_gravity="center_horizontal"
            android:text="mail list"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/faxian"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/faxian_button"
            android:layout_gravity="center_horizontal"
            android:background="@drawable/faxian_fix"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/t3"
            android:layout_gravity="center_horizontal"
            android:text="find"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/wode"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/wode_button"
            android:layout_gravity="center_horizontal"
            android:background="@drawable/wode_fix"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/t4"
            android:layout_gravity="center_horizontal"
            android:text="I"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</LinearLayout>

·Introducing the navigation bar in the activity interface

·Get the viewpager2 object in the activity and set the adapter

 viewPager2 = findViewById(R.id.vp2);
  viewpageradapter = new viewpageradapter(getSupportFragmentManager(), getLifecycle(), fragmentList);
  viewPager2.setAdapter(viewpageradapter);

·Create a fragment (there is only one text control)

·Create adapter (inheriting FragmentStateAdapter instead of FragmentPagerAdapter)
Differences between FragmentPageAdapter and FragmentPageStateAdapter:

The FragmentPageAdapter separates fragments every time it switches pages. It is suitable for fragments with fewer pages to save some memory, which will not have much impact on the system memory

The FragmentPageStateAdapter recycles fragments every time a page is switched. It is suitable for fragments with more pages, so it will not consume more memory

public class viewpageradapter extends FragmentStateAdapter {
	//Receive fragment
    List<Fragment> fragmentList;
    
    public viewpageradapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle,List<Fragment> fragmentList) {
        super(fragmentManager, lifecycle);
        this.fragmentList=fragmentList;
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
    //Return to the fragment interface of the corresponding position
        return fragmentList.get(position);
    }

    @Override
    public int getItemCount() {
    //Returns the number of fragment s
        return fragmentList.size();
    }
}

·The key point is to realize the linkage effect of fragment and navigation bar buttons
To use this callback function: to implement three methods, all we need to implement is the method of changing the page

 viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
 		
 		/**
         * This method is responsible for listening for page offsets
         * @param position The position index of the first page currently displayed. If positionOffset is non-zero, the page position + 1 will be visible.
         * @param positionOffset [0, 1) The value in indicates the offset from the page position.
         * @param positionOffsetPixels A value in pixels indicating the offset from the position.
         */
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels);
            }
		//Solve the version problem of getcolor (can be deleted)
            @RequiresApi(api = Build.VERSION_CODES.M)
         //This method is responsible for switching the page, and the position starts from 0
            @Override
            public void onPageSelected(int position) {
                changetab(position);
            }
		//Called when the scrolling state changes. It is used to find out when the user starts dragging, when to start pseudo dragging, when the pager automatically stabilizes to the current page, or when to stop / idle completely.
            @Override
            public void onPageScrollStateChanged(int state) {
                super.onPageScrollStateChanged(state);
            }
        });
    }

This is the trigger method of the button touch event

 @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        changetab(view.getId());
        return false;
    }

This method is responsible for receiving two different parameters: the current scroll page position and the button id
The page scroll call button is set to the pressed state, and the button is pressed to scroll the page to the corresponding page, so as to realize the linkage effect.

	//The above two references are used to set the text color
 	@RequiresApi(api = Build.VERSION_CODES.M)
    @SuppressLint("ResourceAsColor")
   
    private void changetab(int position) {
    	//Set the pressing state to false and the text color to the initial color before each scroll
        current.setPressed(false);
        currenttext.setTextColor(MainActivity.this.getColor(black));
        switch (position) {
            case R.id.weixin:
            	//The reason why the button id passed in does not need to save the current state / color is that the page scrolling will automatically call the callback function to trigger the above three methods, that is, the changetab method will be called again, but the corresponding position value will be passed in 
                viewPager2.setCurrentItem(0);
                break;
            case 0:
            	//Set text color
                t1.setTextColor(MainActivity.this.getColor(green));
                //Set imageview to pressed state
                weixin_button.setPressed(true);
                //Save current status / color
                current = weixin_button;
                currenttext = t1;
                break;
            case R.id.tongxunlu:
                viewPager2.setCurrentItem(1);
                break;
            case 1:
                t2.setTextColor(MainActivity.this.getColor(green));
                tongxunlu_button.setPressed(true);
                current = tongxunlu_button;
                currenttext = t2;
                break;
            case R.id.faxian:
                viewPager2.setCurrentItem(2);
                break;
            case 2:
                t3.setTextColor(MainActivity.this.getColor(green));
                faxian_button.setPressed(true);
                current = faxian_button;
                currenttext = t3;
                break;
            case R.id.wode:
                viewPager2.setCurrentItem(3);
                break;
            case 3:
                t4.setTextColor(MainActivity.this.getColor(green));
                wode_button.setPressed(true);
                current = wode_button;
                currenttext = t4;
                break;
        }

    }

The source code is as follows:

Maintivity

public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
    List<Fragment> fragmentList;//The fragment collection passes parameters to the adapter
    viewpageradapter viewpageradapter;
    ViewPager2 viewPager2;
    LinearLayout weixin, tongxunlu, faxian, wode;
    ImageView weixin_button, tongxunlu_button, faxian_button, wode_button, current;//Current records the current imageview status
    TextView t1, t2, t3, t4, currenttext;//currenttext records the current text status

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        weixin.setOnTouchListener(this);
        tongxunlu.setOnTouchListener(this);
        faxian.setOnTouchListener(this);
        wode.setOnTouchListener(this);
        viewPager2 = findViewById(R.id.vp2);
        viewpageradapter = new viewpageradapter(getSupportFragmentManager(), getLifecycle(), fragmentList);
        viewPager2.setAdapter(viewpageradapter);
        viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels);
            }

            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void onPageSelected(int position) {
                changetab(position);
            }


            @Override
            public void onPageScrollStateChanged(int state) {
                super.onPageScrollStateChanged(state);
            }
        });
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @SuppressLint("ResourceAsColor")
    private void changetab(int position) {
        current.setPressed(false);
        currenttext.setTextColor(MainActivity.this.getColor(black));
        switch (position) {
            case R.id.weixin:
                viewPager2.setCurrentItem(0);
                Log.d("TAG", "changetab:weixin Press " + weixin_button.isPressed());
                break;
            case 0:
                t1.setTextColor(MainActivity.this.getColor(green));
                weixin_button.setPressed(true);
                Log.d("TAG", "changetab:weixin slide " + weixin_button.isPressed());
                current = weixin_button;
                currenttext = t1;
                break;
            case R.id.tongxunlu:
                viewPager2.setCurrentItem(1);
                Log.d("TAG", "changetab:tongxunlu Press " + tongxunlu_button.isPressed());
                break;
            case 1:
                t2.setTextColor(MainActivity.this.getColor(green));
                tongxunlu_button.setPressed(true);
                Log.d("TAG", "changetab:tongxunlu slide " + tongxunlu.isPressed());
                current = tongxunlu_button;
                currenttext = t2;
                break;
            case R.id.faxian:
                viewPager2.setCurrentItem(2);
                Log.d("TAG", "changetab:faxian Press " + faxian_button.isPressed());
                break;
            case 2:
                t3.setTextColor(MainActivity.this.getColor(green));
                faxian_button.setPressed(true);
                Log.d("TAG", "changetab:faxian slide " + faxian_button.isPressed());
                current = faxian_button;
                currenttext = t3;
                break;
            case R.id.wode:
                viewPager2.setCurrentItem(3);
                Log.d("TAG", "changetab:wode Press " + wode_button.isPressed());
                break;
            case 3:
                t4.setTextColor(MainActivity.this.getColor(green));
                wode_button.setPressed(true);
                Log.d("TAG", "changetab:wode slide " + wode_button.isPressed());
                current = wode_button;
                currenttext = t4;
                break;
        }

    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @SuppressLint("ResourceAsColor")
    private void init() {
        fragmentList = new ArrayList<>();
        fragmentList.add(BlankFragment.newInstance("WeChat"));
        fragmentList.add(BlankFragment.newInstance("contacts"));
        fragmentList.add(BlankFragment.newInstance("find"));
        fragmentList.add(BlankFragment.newInstance("my"));
        weixin = findViewById(R.id.weixin);
        tongxunlu = findViewById(R.id.tongxunlu);
        faxian = findViewById(R.id.faxian);
        wode = findViewById(R.id.wode);
        weixin_button = findViewById(R.id.weixin_button);
        tongxunlu_button = findViewById(R.id.tongxunlu_button);
        faxian_button = findViewById(R.id.faxian_button);
        wode_button = findViewById(R.id.wode_button);
        t1 = findViewById(R.id.t1);
        t2 = findViewById(R.id.t2);
        t3 = findViewById(R.id.t3);
        t4 = findViewById(R.id.t4);
        weixin_button.setPressed(true);
        t1.setTextColor(MainActivity.this.getColor(green));
        current = weixin_button;
        currenttext = t1;
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        changetab(view.getId());
        return false;
    }
}

Maintivity layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/vp2"
        android:layout_height="0dp"
        android:layout_weight="11"
        android:layout_width="match_parent"/>
    <include
        layout="@layout/navigation"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:layout_width="match_parent"/>
</LinearLayout>

viewpagerAdapter

public class viewpageradapter extends FragmentStateAdapter {

    List<Fragment> fragmentList;

    public viewpageradapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle,List<Fragment> fragmentList) {
        super(fragmentManager, lifecycle);
        this.fragmentList=fragmentList;
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return fragmentList.get(position);
    }

    @Override
    public int getItemCount() {
        return fragmentList.size();
    }
}

viewpagerAdapter layout

<?xml version="1.0" encoding="utf-8"?>
<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=".BlankFragment">

    <TextView
        android:id="@+id/ft1"
        android:text="nice"
        android:layout_centerInParent="true"
        android:textSize="50sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

**navigation(Layout only)**
<?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="horizontal">

    <LinearLayout
        android:id="@+id/weixin"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/weixin_button"
            android:layout_gravity="center_horizontal"
            android:background="@drawable/weixinliaotian_fix"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:text="WeChat"
            android:id="@+id/t1"
            android:layout_gravity="center_horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/tongxunlu"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/tongxunlu_button"
            android:layout_gravity="center_horizontal"
            android:background="@drawable/tongxunlu_fix"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/t2"
            android:layout_gravity="center_horizontal"
            android:text="mail list"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/faxian"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/faxian_button"
            android:layout_gravity="center_horizontal"
            android:background="@drawable/faxian_fix"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/t3"
            android:layout_gravity="center_horizontal"
            android:text="find"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/wode"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/wode_button"
            android:layout_gravity="center_horizontal"
            android:background="@drawable/wode_fix"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/t4"
            android:layout_gravity="center_horizontal"
            android:text="I"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>

</LinearLayout>

The picture and color are gone

Posted by IMakeLousyCode on Tue, 30 Nov 2021 11:30:35 -0800