项目地址:
经常用到scrollview嵌套listview,
效果是:listview自己不滚动,随着scrollview的滚动而滚动。
但是有个需求是scrollview嵌套viewpager,viewpager有三个fragment,fragment里有listview。
MainActivity布局
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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:fillViewport="true"
tools:context="example.com.myvplvsv.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_gravity="center"
android:gravity="center"
android:text="Hello World!"
android:textColor="@color/colorAccent"
android:textSize="25sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#e9e9e9"
android:orientation="vertical">
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="12dp">
<TextView
android:id="@+id/tab1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="@string/tab1"
android:textColor="#cccccc"
android:textSize="10sp" />
<TextView
android:id="@+id/tab2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="@string/tab2"
android:textColor="#cccccc"
android:textSize="10sp" />
<TextView
android:id="@+id/tab3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="@string/tab3"
android:textColor="#cccccc"
android:textSize="10sp" />
</LinearLayout>
<View
android:id="@+id/cursor"
android:layout_width="150dp"
android:layout_height="3dp"
android:background="#ff7012" />
</LinearLayout>
<example.com.myvplvsv.view.ViewPagerForScrollView
android:id="@+id/vp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ff4081" />
</LinearLayout>
</ScrollView>
知识点:
1、动画改变字体大小: tab2.animate().scaleX(1.5f).scaleY(1.5f).setDuration(200);
2、布局管理器的使用改变view的位置、大小等
3、viewpager的addOnPageChangeListener监听。
参考:
ViewPropertyAnimator的使用
ViewPager的setOnPageChangeListener方法详解
Android - 布局管理器LayoutInflater及LayoutParams动态设置宽高属性
MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final int TAB_COUNT = 3;
private TextView tab1;
private TextView tab2;
private TextView tab3;
private ViewPager mVp;
private int offset = 0;//初始位置
private View cursor;
private int scrollWidth;
private int currentIndex;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViews();
setListener();
initVp();
initTabs();
}
private void setListener() {
tab1.setOnClickListener(this);
tab2.setOnClickListener(this);
tab3.setOnClickListener(this);
}
private void findViews() {
tab1 = (TextView) findViewById(R.id.tab1);
tab2 = (TextView) findViewById(R.id.tab2);
tab3 = (TextView) findViewById(R.id.tab3);
cursor = findViewById(R.id.cursor);
mVp = ((ViewPager) this.findViewById(R.id.vp));
}
private void initTabs() {
//将顶部文字恢复默认值
setTabsColor(tab1);
tab1.animate().scaleX(1.5f).scaleY(1.5f).setDuration(0);//设置时长为0
//屏幕宽度
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int screenW = dm.widthPixels;
//指示器滚动间隔
scrollWidth = screenW / 3;
//指示器宽度设定
int cursorWidth = (screenW / 6);
//指示器初始位置
offset = (screenW / TAB_COUNT - cursorWidth) / 2;
//布局管理器使用方法一:
// LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(cursor.getLayoutParams());
// layoutParams.width = cursorWidth;
// layoutParams.setMargins(offset, 0, 0, 0);
// cursor.setLayoutParams(layoutParams);
//布局管理器使用方法二:
LinearLayout.LayoutParams cursorLayoutParams = (LinearLayout.LayoutParams) cursor.getLayoutParams();
cursorLayoutParams.width = cursorWidth;
cursorLayoutParams.leftMargin = offset;
cursor.setLayoutParams(cursorLayoutParams);
}
private void initVp() {
ArrayList<Fragment> fragmentLists = new ArrayList<>();
fragmentLists.add(new Fragment1());
fragmentLists.add(new Fragment2());
fragmentLists.add(new Fragment3());
FragmentManager fragmentManager = getSupportFragmentManager();
mVp.setFocusable(false);
mVp.setAdapter(new MyAdapter(fragmentManager, fragmentLists));
mVp.setOffscreenPageLimit(2);
mVp.setCurrentItem(0);
mVp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
switch (position) {
//成功左滑一页(0到1):
// onPageScrolled执行,positionOffset从0开始变大,此时position=0,currentIndex=0
// onPageSelected执行:currentIndex变为1,此时position=0,currentIndex=1
// onPageScrolled继续执行,positionOffset从0开始变大直到无限接近1,此时position=0,currentIndex=1
// 最后onPageScrolled继续执行,positionOffset从无限接近1突然恢复到0,此时position=1,currentIndex=1
case 0:
if (currentIndex == 0) {
setIndicatorPosition(offset + (int) (scrollWidth * positionOffset));
Log.e("000", "0-->currentIndex == 0");
} else if (currentIndex == 1) {
setIndicatorPosition(offset + (int) (scrollWidth * (positionOffset)));
Log.e("000", "0-->currentIndex == 1");
}
break;
case 1:
if (currentIndex == 1) {
setIndicatorPosition(offset + scrollWidth + (int) (scrollWidth * positionOffset));
Log.e("000", "1-->currentIndex == 1");
} else if (currentIndex == 2) {
setIndicatorPosition(offset + scrollWidth + (int) (scrollWidth * (positionOffset)));
Log.e("000", "1-->currentIndex == 2");
}
break;
case 2:
if (currentIndex == 2) {
setIndicatorPosition(offset + scrollWidth * 2);
Log.e("000", "2-->currentIndex == 2");
}
break;
}
}
@Override
public void onPageSelected(int position) {
currentIndex = position;//已选中位置:012
Log.e("000", "onPageSelected==currentIndex==" + currentIndex);
switch (position) {
case 0:
tab1.animate().scaleX(1.5f).scaleY(1.5f).setDuration(200);
tab2.animate().scaleX(1.0f).scaleY(1.0f).setDuration(200);
tab3.animate().scaleX(1.0f).scaleY(1.0f).setDuration(200);
setTabsColor(tab1);
// setIndicatorPosition(offset);
break;
case 1:
tab2.animate().scaleX(1.5f).scaleY(1.5f).setDuration(200);
tab1.animate().scaleX(1.0f).scaleY(1.0f).setDuration(200);
tab3.animate().scaleX(1.0f).scaleY(1.0f).setDuration(200);
setTabsColor(tab2);
// setIndicatorPosition(offset + scrollWidth);
break;
case 2:
tab3.animate().scaleX(1.5f).scaleY(1.5f).setDuration(200);
tab2.animate().scaleX(1.0f).scaleY(1.0f).setDuration(200);
tab1.animate().scaleX(1.0f).scaleY(1.0f).setDuration(200);
setTabsColor(tab3);
// setIndicatorPosition(offset + scrollWidth * 2);
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void setIndicatorPosition(int offset) {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(cursor.getLayoutParams());
layoutParams.setMargins(offset, 0, 0, 0);
cursor.setLayoutParams(layoutParams);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tab1:
mVp.setCurrentItem(0);
break;
case R.id.tab2:
mVp.setCurrentItem(1);
break;
case R.id.tab3:
mVp.setCurrentItem(2);
break;
}
}
private void setTabsColor(TextView textView) {
tab1.setTextColor(ContextCompat.getColor(this, R.color.defalut_color));
tab2.setTextColor(ContextCompat.getColor(this, R.color.defalut_color));
tab3.setTextColor(ContextCompat.getColor(this, R.color.defalut_color));
textView.setTextColor(ContextCompat.getColor(this, R.color.select_color));
}
}
ViewPagerForScrollView
解决viewpager(内含listview)随scrollview一起滑动
/**
* ScrollView嵌套viewpager
*/
public class ViewPagerForScrollView extends ViewPager {
public ViewPagerForScrollView(Context context) {
super(context);
}
public ViewPagerForScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height)
height = h;
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
MyListView
解决listview不显示
public class MyListView extends ListView {
public MyListView(Context context) {
super(context);
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* 自适应
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
Fragment1
需设置 mLv.setFocusable(false);解决不置顶的问题
public class Fragment1 extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment1_layout, container, false);
ListView mLv = ((ListView) view.findViewById(R.id.lv));
mLv.setDivider(new ColorDrawable(Color.parseColor("#ff0000")));
mLv.setDividerHeight(5);
mLv.setFocusable(false);
return view;
}
}
最后
这样就实现了viewpager随scrollview一起滚动 ,但是还有一个问题就是如果三个fragment页面的listview高度不统一,那么fragment将依靠最高的那一个为准,也就是说会有比较矮的fragment有空白。
比如: