周末刚过,对于礼拜一可能大家的心情还沉浸在周末那种放松的那种状态下。我也是。出于无聊,随便翻看了一下之前写过的一个商城类项目,来这里和大家分享其中的一个小功能,就当是练练手,进入工作状态。
在这里声明一下,由于本人属于一个典型的懒程序员,文字叙述也不是很好。能写博客已经是极限了,哈哈。所以以后我的博客习惯都是先看效果图然后在看具体代码和实现。(因为我实在不想用文字去叙述一个功能效果)好了,手指已经很累了,打这么字确实很不容易,小时候作文经常挨老师批评,上图吧
。
相信大家看到了,这种类似的需求在开放中还是很常见的,其实实现的方式也很多,今天我们来学习一下它是如何实现的。
首先梳理一下,用到的知识点,ViewPager,Fragment,BitmapFactory,Matrix
具体的不再详细介绍了,代码里面注释写的比较详细。
- 首先我们先创建两个fragment。分别作为 宝贝,店铺的布局界面
package achoice.com.taba;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* 作者:${NanFeiLong}
* 日期 2016/12/9 17:26
* 宝贝对应的fragment
*/
public class BaoBeiFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.baobei,container,false);
return view;
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:textSize="24dp"
android:padding="15dp"
android:textColor="#969696"
android:text="您还没有收藏任何宝贝哦!"/>
LinearLayout>
店铺的Fragment和布局文件也类似。因为两个基本相同,这里就不用给出了,有兴趣的可以下载源码。
package achoice.com.taba;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends FragmentActivity implements View.OnClickListener, ViewPager.OnPageChangeListener {
// ViewPager适配器
private ViewPager mViewPager;
private FragmentAdapter mFragmentAdapter = null;
private int tabWidth;
private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
//图片选择条
private ImageView mivBottom_line;
// 宝贝
private TextView mtvBaoBei;
// 店铺
private TextView mtvStore;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mivBottom_line = (ImageView) findViewById(R.id.img_tabLine);
mtvBaoBei = (TextView) findViewById(R.id.tv_baobei);
mtvStore = (TextView) findViewById(R.id.tv_store);
mtvBaoBei.setTextColor(getResources().getColor(R.color.checked_textcolor));
//图片选择条
initData();
mFragmentAdapter = new FragmentAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mFragmentAdapter);
mtvBaoBei.setOnClickListener(this);
mtvStore.setOnClickListener(this);
mViewPager.setOnPageChangeListener(this);
}
/**
* 配置图片选择条
*/
private void initData() {
getWindowManager().getDefaultDisplay().getMetrics(mDisplayMetrics);
tabWidth = mDisplayMetrics.widthPixels / 2;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bottom_line);
// 设置图片选择条的宽高
Bitmap bitmap1 = Bitmap.createBitmap(bitmap, 0, 0, tabWidth, 8);
mivBottom_line.setImageBitmap(bitmap1);
}
/**
* 点击监听
*
* @param view
*/
@Override
public void onClick(View view) {
switch (view.getId()) {
// 宝贝
case R.id.tv_baobei: {
TextTab();
mtvBaoBei.setTextColor(getResources().getColor(R.color.checked_textcolor));
mViewPager.setCurrentItem(0);
}
break;
// 店铺
case R.id.tv_store: {
TextTab();
mtvStore.setTextColor(getResources().getColor(R.color.checked_textcolor));
mViewPager.setCurrentItem(1);
}
break;
default:
break;
}
}
/**
* 正在滑动时
* @param position
* @param positionOffset 当前页面偏移的百分比[0,1)
* @param positionOffsetPixels 当前页面偏移的像素位置
*/
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// Matrix创建一个矩形
Matrix matrix = new Matrix();
switch (position) {
case 0:
// 使用setTranslate直接位置
matrix.setTranslate(0, 0);
break;
case 1:
matrix.setTranslate(tabWidth, 0);
break;
}
// 在滑动的过程中,计算出图片选择条的动态滑动距离
//这里用了"后乘"positionOffset[0,1)
float miters = (tabWidth) * positionOffset;
// 使用postTranslate动态追加滑动距离
matrix.postTranslate(miters, 0);
mivBottom_line.setImageMatrix(matrix);
}
/**
* 滑动完毕时
* @param position 滑动完毕时 停留在的页面
*/
@Override
public void onPageSelected(int position) {
switch (position) {
case 0: {
TextTab();
mtvBaoBei.setTextColor(getResources().getColor(R.color.checked_textcolor));
mViewPager.setCurrentItem(0);
}
break;
case 1: {
TextTab();
mtvStore.setTextColor(getResources().getColor(R.color.checked_textcolor));
mViewPager.setCurrentItem(1);
}
break;
default:
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
/**
* 文字全部重置为默认状态
*/
private void TextTab() {
mtvBaoBei.setTextColor(getResources().getColor(R.color.default_color));
mtvStore.setTextColor(getResources().getColor(R.color.default_color));
}
}
这里大概说一下,viewpager的滑动和fragment的切换,这些没什么说的,关键点比较绕的是下面的图片选择滑动条的处理。
tabWidth = mDisplayMetrics.widthPixels / 2;
float miters = (tabWidth) * positionOffset;
// 使用postTranslate动态追加滑动距离
matrix.postTranslate(miters, 0);
mivBottom_line.setImageMatrix(matrix);
positionOffset参数为viewpager在滑动时的偏移量取值[0,1),tabWidth图片滑动条的宽度,这里也就是屏幕的1/2。这样我们就能得到图片滑动时的动态”宽度”了。
得到动态”宽度”后,然后在调用Matrix的postTranslate(float dx, float dy)方法。这个方法的叫做”后乘”,可能大家对这个比较陌生,其实我刚开始看到后也是理解不了,不过没关系,这里我给大家推荐一篇文章Android之Matrix的用法 。其实就是每次的平移完成后状态保持然后继续下一次平移得到最后一次的平移位置。比如说第一次平移到(0.5,0)位置,停止下来,第二次平移到(0.6,0)位置停止下来,那么最后我们看到的结果是显示停留在(0.6,0)位置的图片的。
3.最后
我们还写了一个TextTab()方法。其作用就是每当点击选项卡或者滑动页面时候,都先把选项卡文字都设置成位选中颜色状态,然后根据position在设置其选中状态时候对应的选项卡颜色和状态。
/**
* 文字全部重置为默认状态
*/
private void TextTab() {
mtvBaoBei.setTextColor(getResources().getColor(R.color.default_color));
mtvStore.setTextColor(getResources().getColor(R.color.default_color));
}
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f1f1f1"
android:orientation="vertical"
tools:context="achoice.com.taba.MainActivity">
<LinearLayout
android:id="@+id/llyout_my_coupon_sort"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_baobei"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#f8f8f8"
android:paddingTop="10dp"
android:paddingBottom="15dp"
android:gravity="center"
android:text="宝贝(0)"
android:textStyle="bold"
android:textSize="16sp"/>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:background="#d7d7d7"/>
<TextView
android:id="@+id/tv_store"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#f8f8f8"
android:paddingTop="10dp"
android:paddingBottom="15dp"
android:gravity="center"
android:textStyle="bold"
android:text="店铺(0)"
android:textSize="16sp"/>
LinearLayout>
<ImageView
android:id="@+id/img_tabLine"
android:layout_width="match_parent"
android:layout_height="3dp"
android:contentDescription="@null"
android:scaleType="matrix"/>
<View
android:layout_width="match_parent"
android:layout_height="0.3dp"
android:layout_marginBottom="5dp"
android:background="#d7d7d7"/>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
LinearLayout>
<resources>
<color name="colorPrimary">#3F51B5color>
<color name="colorPrimaryDark">#303F9Fcolor>
<color name="colorAccent">#FF4081color>
<color name="textcolor_mine_normal">#666666color>
<color name="checked_textcolor">#f56a30color>
<color name="default_color">#898787color>
resources>
好了,就说到这里,项目已经上传,有兴趣的可以下载源码