Android中顶部Tab带滑动选项卡之二选一,仿淘宝宝贝收藏和店铺收藏

原创 2016年12月12日 16:29:37

周末刚过,对于礼拜一可能大家的心情还沉浸在周末那种放松的那种状态下。我也是。出于无聊,随便翻看了一下之前写过的一个商城类项目,来这里和大家分享其中的一个小功能,就当是练练手,进入工作状态。

在这里声明一下,由于本人属于一个典型的懒程序员,文字叙述也不是很好。能写博客已经是极限了,哈哈。所以以后我的博客习惯都是先看效果图然后在看具体代码和实现。(因为我实在不想用文字去叙述一个功能效果)好了,手指已经很累了,打这么字确实很不容易,小时候作文经常挨老师批评,上图吧


效果图
相信大家看到了,这种类似的需求在开放中还是很常见的,其实实现的方式也很多,今天我们来学习一下它是如何实现的。

首先梳理一下,用到的知识点,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;
    }


}
  • 对应的layout文件baobei.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: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和布局文件也类似。因为两个基本相同,这里就不用给出了,有兴趣的可以下载源码。

  • 下来是MainActivity,这里我们让其继承自FragmentActivity点击事件和滑动事件都用实现接口的方式去实现监听
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的切换,这些没什么说的,关键点比较绕的是下面的图片选择滑动条的处理。

  1. 首先
    我们对图片宽高进行适配,这里高度我们在xml中设置了,宽度占用手机屏幕的1/2。
    调用 tabWidth = mDisplayMetrics.widthPixels / 2;
  2. 然后
    我们在重写的onPageScrolled(当滑动进行时)方法中调用Matrix 绘制一个矩形。在调用matrix.setTranslate(tabWidth, 0);方法实现图片滑动条位置。其实就是通过计算平移距离来实现确定位置的。对于动态中图片滑动条的位置,我们来分析这几行代码
      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));
    }
  • 布局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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>
  • 还有colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>


    <color name="textcolor_mine_normal">#666666</color>
    <color name="checked_textcolor">#f56a30</color>
    <color name="default_color">#898787</color>
</resources>
好了,就说到这里,项目已经上传,有兴趣的可以下载源码

源码

版权声明:本文为博主原创文章,未经博主允许不得转载。

android-高仿手机淘宝--商铺界面产品展示及图片缩放

高仿手机淘宝--商铺界面产品展示及图片缩放
  • tzr0330
  • tzr0330
  • 2015年04月12日 13:59
  • 1255

【Android性能优化】(一)使用SparseIntArray替换HashMap

【Android性能优化】之使用SparseIntArray替换HashMap
  • gogler
  • gogler
  • 2013年11月13日 10:50
  • 14140

【Android UI设计与开发】第11期:顶部标题栏(二)ActionBar实现Tab选项卡和下拉导航列表

转载请注明出处:http://blog.csdn.net/yangyu20121224/article/details/9050573         在上一篇文章中,我...

【Android UI设计与开发】第11期:顶部标题栏(二)ActionBar实现Tab选项卡和下拉导航列表

在上一篇文章中,我们只是大概的了解了一下关于ActionBar这个类的简单用法,今天我会继续以实例进行更加深入的讲解。   一、实现Tab选项标签          当你想要在一个Activity中提...

【Android UI设计与开发】第11期:顶部标题栏(二)ActionBar实现Tab选项卡和下拉导航列表

转载请注明出处:http://blog.csdn.net/yangyu20121224/article/details/9050573         在上一篇文章中,我...

仿qq顶部栏tab选项卡切换效果

如图,是实现当前tab页的效果,点击的时候两边切换,实现的效果和qq页面的消息电话顶部栏是一样的.。 首先看一下布局文件R.layout.activity_main     android:lay...

仿微信顶部选项卡(二)

  • 2014年09月29日 18:41
  • 4.37MB
  • 下载

android应用开发--------------看RadioGroup源码,写类似单选选项卡的集成控件(如底部导航,tab等等)

博客为 有时个哥 原创,如需转载请标明出处: 上面就是需求设计,4个类似的布局控件,每次只能选择一个,然后得到上面对应的钱数。(上面只是效果图,实际数据是从服务器获取,然后付到控件上) 看到这种,我...
  • ls703
  • ls703
  • 2015年06月30日 15:14
  • 2053
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android中顶部Tab带滑动选项卡之二选一,仿淘宝宝贝收藏和店铺收藏
举报原因:
原因补充:

(最多只允许输入30个字)