1. Requirement description
There is a requirement to use the ViewPager to slide images, with a TAB below it, and each TAB TAB corresponds to a group of images. When the image in the ViewPager switches to the next group, the TAB TAB also switches.
2. Solution
See the above requirements I first think of using two layers of ViewPager implementation, each group of pictures using a ViewPager, the outermost layer and then use a ViewPager + TabLayout linkage switch, the inner layer of ViewPager event interception can be. However, after doing this, I found that the inner ViewPager was always skipped when I quickly swiped. Later, you might want to use a ViewPager and manually switch the TabLayout TAB to the next one when the current group of images is displayed. Follow this line of thinking, perfect fulfillment of requirements. And the code package, for students who need direct use. Source code address: github.com/talonerain/…
3. Effect display
Apk download address github.com/talonerain/…
4. Usage
1. In project Gradle add:
allprojects {
repositories {
maven { url 'https://www.jitpack.io'}}}Copy the code
2. Add to moudle Gradle:
compile 'com. Making. Talonerain: db - viewpager - image: v1.0.0'
Copy the code
3. Introduce the following into the XML layout file:
<com.lsy.view.DbVPager
android:id="@+id/db_vpager"
android:layout_width="match_parent"
android:layout_height="400dp" />
Copy the code
4. Set the TAB position (above or below the image)
db_vpager.setBarPosition(DbVPager.BarPositon.BOTTOM);
Copy the code
5. Set the image data source and group name
List<String> imgList1 = new ArrayList<>();
imgList1.add(url1);
imgList1.add(url2);
ImgGroups group1 = new ImgGroups(groupName1, imgList1);
List<String> imgList2 = new ArrayList<>();
imgList2.add(url3);
imgList2.add(url4);
ImgGroups group2 = new ImgGroups(groupName2, imgList2);
List<ImgGroups> data = new ArrayList<>();
data.add(group1);
data.add(group2);
db_vpager.setSource(data);
Copy the code
6. Switch the callback
Calls back to the position and display text of the current TabLayout TAB.
db_vpager.addTabChangeListenr(new DbVPager.DbCallbackListener() {
@Override
public void callback(int index, String text) {
tv_showText.setText("Current classification:"+ text); }});Copy the code
7. Display controls
db_vpager.show();
Copy the code
5. Code parsing
1. Control 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<android.support.design.widget.TabLayout
android:id="@+id/tab1"
android:layout_width="match_parent"
android:layout_height="35dp"
app:tabMode="fixed"
app:tabGravity="fill"
android:layout_alignParentTop="true"/>
<android.support.design.widget.TabLayout
android:id="@+id/tab2"
android:layout_width="match_parent"
android:layout_height="35dp"
app:tabMode="fixed"
app:tabGravity="fill"
android:layout_alignParentBottom="true"/>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_above="@+id/tab2"
android:layout_below="@+id/tab1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Copy the code
Since the TAB position can be either up or down, I placed a TabLayout above and below. Depending on which TAB is displayed, I use the following code to get the TAB, without worrying about which TAB is displayed in the logical code.
private TabLayout getTab(a) {
return tab1.getVisibility() == VISIBLE ? tab1 : tab2;
Copy the code
2. Data analysis
As you can see in step 5 of using methods, the data source for the control is a list like this:
List<ImgGroups> mDataSource;
Copy the code
ImgGroups type:
public class ImgGroups { public String groupName; Public List<String> imgList; ImgGroups(String name, List<String> imgList) {this.groupName = name; this.imgList = imgList; }}Copy the code
For the data source, we need to parse it into two parts, one is the list of all images to display on the ViewPager, the list is not concerned with classification, and the other part is the need to switch the TAB position, that is, when the image slides to a certain position, the TAB needs to switch the label, we call the index array. The code is as follows:
private void initData(a) {
indexList = new int[mDataSource.size()]; / / an array index
imgList = new ArrayList<>(); / / image list
Iterator<ImgGroups> iterator = mDataSource.iterator();
int i = 0;
while (iterator.hasNext()) {
// Iterate over the data source list
ImgGroups item = iterator.next();
TabLayout.Tab tab = getTab().newTab(); // Each group of images corresponds to a TAB
if (null! = item &&null! = item.imgList && item.imgList.size() >0) {
// When the current group of images is finished, you need to switch the TAB position
if (i > 0) {
int temp = indexList[i - 1];
indexList[i++] = temp + item.imgList.size();
} else {
indexList[i++] = item.imgList.size();
}
String text = TextUtils.isEmpty(item.groupName) ? "null" : item.groupName;
tab.setText(text); // Sets the current TAB textgetTab().addTab(tab); imgList.addAll(item.imgList); }}}Copy the code
3. The ViewPager code
In ViewPager, we need to decide which image to slide to, and to get that position, we also need to determine the direction of the ViewPager slide, because the target position is different when you swipe left and when you swipe right. The difference is that when you swipe left, you swipe TAB when the current image is the last one in the group. Toggle TAB when the current image is the first in the group while right – swiping. This part of the code is not easy to describe, we can analyze the next:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (vpPosition > position) {
isToLeft = true; / / the left slide}else if(vpPosition<position) {
isToLeft = false; } vpPosition = position;if(! tabScrolling) {if (isToLeft) {
int index = Arrays.binarySearch(indexList, position + 1);
if (index >= 0) {
TabLayout.Tab tab = getTab().getTabAt(index);
if(tab ! = null) {if(mListener ! = null) { mListener.callback(tab.getPosition(), tab.getText().toString()); } vpScrolling =true; // Prevent TabLayout from switching ViewPager tab.select(); vpScrolling =false; }}}else {
int index = Arrays.binarySearch(indexList, position);
if (index >= 0) {
TabLayout.Tab tab = getTab().getTabAt(index + 1);
if(tab ! = null) {if(mListener ! = null) { mListener.callback(tab.getPosition(), tab.getText().toString()); } vpScrolling =true;
tab.select();
vpScrolling = false;
}
}
}
}
vpScrolling = false;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
Copy the code
4. TabLayout code
In TabLayout we need to make sure that the ViewPager displays the first image of the group when the TAB is toggled as follows:
getTab().addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
if(mListener ! = null) { mListener.callback(tab.getPosition(), tab.getText().toString()); }if(! vpScrolling) { int index = tab.getPosition(); int pos;if (index == 0) {
pos = 0;
} elsePosition pos = indexList[tab.getPosition() -1]; } tabScrolling =true; Viewpager. setCurrentItem(pos); tabScrolling =false;
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
Copy the code
5. Fault tolerant processing
In the code above, there are two labeled variables, vpScrolling and tabScrolling. If you set ViewPager and TabLayout separately, you’ll notice that when you set TabLayout in the ViewPager, the code in the TabLayout will in turn make the ViewPager slide, causing it to display incorrectly. The same is true for sliding ViewPager inside a TabLayout. To do this, we set two tag variables to make sure that the TabLayout and ViewPager switch without affecting the other.