2017-05-05 09:41:15 qq_26570353 阅读数 2065
  • Android 项目实战-影讯

    本课程包含14个小节课程,内容包括:影讯项目演示,影讯项目架构,使用聚合API后台,封装Volley网络框架,根据JSON格式创建JavaBean,实现底部导航 ,实现侧滑菜单,实现MovieDao,实现可索引ListView,集成百度地图实现定位,实现首页电影列表,实现电影详情,实现影院列表,实现影院详细。

    6649 人正在学习 去看看 郭宏志

## 源代码下载:http://download.csdn.net/detail/qq_26570353/9833991 ##


启动页 ViewPager+Fragement 程序引导页 FragmentTabHost+Fragment底部导航栏


欢迎页 启动页 延时启动

第二次以及之后再启动,直接由启动页,跳转到主页面。


本次实现的内容和知识如下,不太了解的可以去查看对应知识点:
1.程序启动页,实现延时一秒启动,知识:Handler postDelayed或者定时器实现等等均可

2.ViewPager+Fragment实现程序引导页,并设置指示器。

3.FragmentTabHost+Fragment实现底部导航栏,参考了博客:http://blog.csdn.net/yangyu20121224/article/details/9016223

4.Fragment中Button点击事件响应,由于会出现按钮不响应事件,网上也有介绍,可以去看看

5.Selector实现底部选中的图标和颜色切换,这里用Android Studio的Selector插件快速生成。

代码部分:为方便看懂,这里做大致介绍:

MainActivity.java: 程序的主体部分,

AppGuide: App的程序引导页部分

Fragment_Tab: 底部导航栏的Fragment

welcomePage: 程序每次启动都会看到的启动页实现部分
这里写图片描述

WelcomePage.java:
布局文件:

<?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="vertical" >
    <ImageView 
        android:id="@+id/imgView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/guide_img1"
        />

</LinearLayout>

代码:

public class WelcomePage extends Activity {
    //使用Handler实现延时或者定时器也可以
    private Handler handler;
    private boolean isFirst=true;
    private Intent intent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.welcome_page);

        //将是否是第一次的状态用SharedPreferences保存和取出
        final SharedPreferences sp= getSharedPreferences("FirstLaunch",MODE_PRIVATE);
        isFirst=sp.getBoolean("FirstValue",true);
        handler=new Handler();

        handler.postDelayed(new Runnable() {        
            @Override
            public void run() {
                if(isFirst){
                    //修改状态,并跳转到引导页
                    sp.edit().putBoolean("FirstValue", false).commit();
                    intent=new Intent(WelcomePage.this, AppGuide.class);
                    startActivity(intent);
                }else{
                    //不是第一次进入该APP,则跳转到MainActivity
                    intent=new Intent(WelcomePage.this, MainActivity.class);
                    startActivity(intent);
                }
                finish();
            }
        }, 1000);
    }
}

注意:需要将Manifest的启动改为welcomePage,后面再给出Manifest配置文件。


AppGuide.java:

public class AppGuide extends FragmentActivity implements OnClickListener,OnPageChangeListener {
    private Button btnStart;
    private ViewPager viewPager;
    private GuideFragmentAdapter guideFragmentAdapter;
    private List<Fragment> fragmentList;
    private ImageView[] imageViews=new ImageView[4];
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.app_guide);

        //initView
        btnStart=(Button) findViewById(R.id.btnStart);
        viewPager=(ViewPager) findViewById(R.id.viewPager);
        fragmentList=new ArrayList<Fragment>();

        //这么说吧,类似List<String> data--------这是准备数据源
        fragmentList.add(new GuideFragment1());
        fragmentList.add(new GuideFragment2());
        fragmentList.add(new GuideFragment3());
        fragmentList.add(new GuideFragment4());
        //-----------------
        imageViews[0]= (ImageView) findViewById(R.id.guidedot_1);
        imageViews[1]= (ImageView) findViewById(R.id.guidedot_2);
        imageViews[2]= (ImageView) findViewById(R.id.guidedot_3);
        imageViews[3]= (ImageView) findViewById(R.id.guidedot_4);

        //创建适配器
        guideFragmentAdapter=new GuideFragmentAdapter(getSupportFragmentManager(), fragmentList);
        //视图加载适配器
        viewPager.setAdapter(guideFragmentAdapter);
        //事件
        viewPager.setOnPageChangeListener(this);
        btnStart.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            //开始体验的按钮
        case R.id.btnStart:
            Intent intent=new Intent(this, MainActivity.class);
            startActivity(intent);
            this.finish();
            break;

        default:
            break;
        }

    }
    @Override
    public void onPageScrollStateChanged(int arg0) {

    }

    //滑动到最后一页,显示按钮
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        //如果滑动到最后一页,则把“开始体验”显示出来
        if(position==fragmentList.size()-1){
            btnStart.setVisibility(View.VISIBLE);
        }else {
            btnStart.setVisibility(View.GONE);
        }
        for(int i=0;i<4;i++){
            if(i==position){
                imageViews[i].setSelected(true);
            }else {
                imageViews[i].setSelected(false);
            }
        }
    }

appguide对应布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </android.support.v4.view.ViewPager>

    <!-- 指示点 -->
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="100dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true">

        <ImageView
            android:id="@+id/guidedot_1"
            android:padding="15dip"
            android:layout_gravity="center_horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/guide_dot" />
        <ImageView
            android:id="@+id/guidedot_2"
            android:padding="15dip"
            android:layout_gravity="center_horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/guide_dot" />
        <ImageView
            android:id="@+id/guidedot_3"
            android:padding="15dip"
            android:layout_gravity="center_horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/guide_dot" />
        <ImageView
            android:id="@+id/guidedot_4"
            android:padding="15dip"
            android:layout_gravity="center_horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/guide_dot" />
    </LinearLayout>
    <Button
        android:id="@+id/btnStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:gravity="center_horizontal"
        android:layout_marginBottom="20dp"
        android:background="#00aa00"
        android:text="开始体验"
        android:padding="15dp"
        android:textSize="30sp"
        android:textColor="#FFFFFF"
        android:visibility="gone" />

</RelativeLayout>

guideFragment1.java:

public class GuideFragment1 extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.guide_fragment1, container, false);
    }
}

对应布局:

<?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="vertical" >
    <ImageView 
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/guide_img2"
        />

</LinearLayout>

GuideAdapter:适配器

public class GuideFragmentAdapter extends FragmentStatePagerAdapter {

    private List<Fragment> fragmentList;

    public GuideFragmentAdapter(FragmentManager fm, List<Fragment> fragmentList) {
        super(fm);
        this.fragmentList=fragmentList;
    }

    @Override
    public Fragment getItem(int arg0) {
        return fragmentList.get(arg0);
    }

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

    //item销毁
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
    }

    //item初始化
    @Override
    public Object instantiateItem(ViewGroup arg0, int arg1) {
        return super.instantiateItem(arg0, arg1);
    }
}

至此,程序启动到引导页,应该是结束了的,下面是底部导航栏:
activity_main布局:

<?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:orientation="vertical"
    tools:context="com.a1141705068qq.class_one.com.a1141705068qq.aa.MainActivity">
    <FrameLayout
        android:id="@+id/home_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        >
    </FrameLayout>

    <View android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:alpha="0.6"
        android:background="@android:color/darker_gray"
        />

    <android.support.v4.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_marginTop="3dp"
        android:layout_height="wrap_content">
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"
            >
        </FrameLayout>
    </android.support.v4.app.FragmentTabHost>

</LinearLayout>

tab布局:也就是设置一个图片,底部是文字

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/img_tab"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:focusable="false"
        android:padding="3dp" 
        android:src="@drawable/home_seletor">
    </ImageView>

    <TextView
        android:id="@+id/tv_tab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:text="首页"
        android:textSize="15sp"
        android:textColor="@drawable/tab_text_selecor">
    </TextView>

</LinearLayout>

Fragment1.Java:遇到过按钮点击无响应,原因在于Fragment中的响应的写法变了一点点。其他的Fragment就是一个TextView,并且类似。这个布局只是多加了一个按钮,布局就不贴了,代码如下:

public class FragmentPage1 extends Fragment{

    private View view;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        view=inflater.inflate(R.layout.tab_fragment1, null);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        //按钮事件响应的一种写法,在onActivityCreated写,也有其他写法,这里只是其一。
        Button button = (Button) getActivity().findViewById(R.id.frag1_btn1);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(),"响应成功",Toast.LENGTH_SHORT).show();
            }
        });
    }

MainActivity.java: 代码写了注释,应该可以看懂,需要用到上面的布局文件和内容,所以现在贴出,代码如下:

public class MainActivity extends AppCompatActivity{

    //定义对象
    private FragmentTabHost mTabHost;
    private LayoutInflater layoutInflater;

    //定义数组来存放Fragment界面\图片、文字
    private Class fragmentArray[] = {FragmentPage1.class, FragmentPage2.class, FragmentPage3.class,
            FragmentPage4.class};

    private int mImageViewArray[] = {R.drawable.home_seletor,R.drawable.info_seletor,
            R.drawable.my_selector, R.drawable.setting_selector};

    private String mTextviewArray[] = {"首页", "消息", "我的", "设置"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        //实例化布局对象
        layoutInflater = LayoutInflater.from(this);

        //实例化TabHost对象,得到TabHost
        mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
        mTabHost.setup(this, getSupportFragmentManager(), R.id.home_container);
        //设置取消分割线
        mTabHost.getTabWidget().setDividerDrawable(null);
        //得到fragment的个数
        int count = fragmentArray.length;
        for(int i = 0; i < count; i++){
            //为每一个Tab按钮设置图标、文字和内容
            TabHost.TabSpec tabSpec = mTabHost.newTabSpec(mTextviewArray[i]).setIndicator(getTabItemView(i));
            //将Tab按钮添加进Tab选项卡中
            mTabHost.addTab(tabSpec, fragmentArray[i], null);

        }

    }//end of initView

    /**
     * 给Tab按钮设置图标和文字
     */
    public View getTabItemView(int index){
        View view = layoutInflater.inflate(R.layout.tab_item_view, null);
        ImageView imageView = (ImageView) view.findViewById(R.id.img_tab);
        imageView.setImageResource(mImageViewArray[index]);
        TextView textView = (TextView) view.findViewById(R.id.tv_tab);
        textView.setText(mTextviewArray[index]);
        return view;
    }

}

AndroidMainifest.xml: 注意的是将第一个activity修改成welcomPage,这样每次都是APP从这个Activity先启动,才可以看见启动页。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.a1141705068qq.class_one">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.Light.NoActionBar">
        <activity android:name="com.xqliu.welcomepage.WelcomePage">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.a1141705068qq.main.MainActivity"></activity>
        <activity android:name="com.xqliu.appguide.AppGuide"></activity>
    </application>

</manifest>

源代码下载:http://download.csdn.net/detail/qq_26570353/9833991

2018-10-22 17:36:46 sinat_28864443 阅读数 314
  • Android 项目实战-影讯

    本课程包含14个小节课程,内容包括:影讯项目演示,影讯项目架构,使用聚合API后台,封装Volley网络框架,根据JSON格式创建JavaBean,实现底部导航 ,实现侧滑菜单,实现MovieDao,实现可索引ListView,集成百度地图实现定位,实现首页电影列表,实现电影详情,实现影院列表,实现影院详细。

    6649 人正在学习 去看看 郭宏志
2016-11-25 21:24:03 qingqingziyu520 阅读数 3450
  • Android 项目实战-影讯

    本课程包含14个小节课程,内容包括:影讯项目演示,影讯项目架构,使用聚合API后台,封装Volley网络框架,根据JSON格式创建JavaBean,实现底部导航 ,实现侧滑菜单,实现MovieDao,实现可索引ListView,集成百度地图实现定位,实现首页电影列表,实现电影详情,实现影院列表,实现影院详细。

    6649 人正在学习 去看看 郭宏志

TabBar这个名字相信很多学过一点IOS程序员都知道它是用来干嘛的,但本人也并非擅长开发IOS程序员,只是略懂略懂....这是一个很强大的TabBar,可满足很多需求。用起来也非常简单,在oncreate只调用一行代码就把UI布局和切换页面功能基本都实现了。具体实现的功能,请看效果图:

主

使用方法:

1.引入Gradle依赖
 repositories { 
       jcenter()   
 }   

 dependencies{     
   compile 'com.jpeng:JPTabBar:1.0.4'   
 }
2.在你的主页面XML,在适当位置添加下面代码

<com.jpeng.jptabbar.JPTabBar
    android:layout_alignParentBottom="true"
    android:id="@+id/tabbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#fff"
    app:TabHeight="56dp"
    app:BadgeDraggable="true"
    app:TabAnimate="Jump"
    app:BadgePadding="4dp"
    app:BadgeMargin="5dp"
    app:BadgeTextSize="10dp"
    />
3.在你的Activity里面声明注解变量。(seleIcons和BadgeModes可以不声明,还有你要确保你全部数组的长度是一样的)

//设置标题
@Titles
private static final String[] mTitles={"微信","通讯录","发现",""};

//设置选中图标
@SeleIcons
private static final int[] mSelectIcons={R.mipmap.al_,R.mipmap.al8,R.mipmap.alb,R.mipmap.ald};

//设置未选中图标
@NorIcons
private static final int[] mNormalIcon={R.mipmap.ala,R.mipmap.al9,R.mipmap.alc,R.mipmap.ale};

经过上面的设置后,基本上就可以把一个底部的UI搭建了!
但还有一步,想达到Wechat那种渐变和自动切换ViewPager就使用这个方法:

 mTabBar.setContainer(mVp);  //mVp是ViewPager对象

方法和节点说明:

JPTabBar主要方法:

 /**     * 设置自定义Tab切换动画     */    public void setCustomAnimate(Animatable customAnimate);     
/** 显示BadgeView ,传入字符串     * 当然还有一个重载方法,第二个参数为int,设置消息数量     * 传入""字符串显示圆点     */    public void ShowBadge(int position,String text);    /**     * 隐藏BadgeView     */    public void HideBadge(int position);    /**     * 切换Tab页面,是否带动画     */    public void setSelectTab(int index, boolean animated);    /**     * 设置点击TabBar事件的观察者     */    public void setTabListener(OnTabSelectListener listener);    /**     * 设置badgeView消失的回调事件     */    public void setDismissListener(BadgeDismissListener listener);

结点说明:

结点名字 结点说明 参数类型 默认值
TabHeight TabBar的高度,将会覆盖layout_height的设置 dimension 56dp
TabNormalColor 字体和图标的未选中颜色 color 0xffAEAEAE(灰色)
TabSelectColor 字体和图标的选中的颜色 color 0xff59D9B9(青色)
TabTextSize Tab底部文件大小 dimension 14sp
TabIconSize Tab图标的大小 dimension 24dp
TabIconFilter 设置图标是否随着字体颜色而改变 boolean true
TabMargin 设置图标距离上面和文字距离下面的距离 dimension 8dp
TabSelectBg 设置TabBarItem选中的背景颜色 color 透明
TabDuration Tab切换的动画时间 Integer 500
TabAnimate Tab切换的动画类型 enum Flip
TabMiddleIcon Tab中间的图标 drawable
BadgeColor 徽章的背景颜色 color #f00(红色)
BadgeDraggable 徽章是否可以拖动 boolean false
BadgePadding 徽章的背景扩展距离 dimension 4dp
BadgeTextSize 徽章显示的字体大小 dimension 11dp
BadgeMargin 徽章距离右边边缘的间隔 dimension 9dp

注意事项

1.假如你已经给TabBar setContainer,不要setOnPageChangeListener给ViewPager

/**    *如果你前面已经给TabBar设置了容器,然后调用这个方法的话,类似WeChat那种拖动渐变效果以及自动切换页面将会失效    *假如你要监听页面改变事件,可以使用TabListener   */  mPager.setOnPageChangeListener(this);

2.假如你要实现中间凸出的按钮,必须要在主界面最外围的父结点设置 android:clipChildren="false",否则会遮盖

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:jp="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:gravity="bottom"
    android:orientation="vertical"
    >



下面是实现微信底部导航栏的完整代码:

activity的xml代码:

<?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:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context="com.cf.android_navigtionbottombar.MainActivity">
   <android.support.v4.view.ViewPager
       android:id="@+id/vp"
       android:layout_above="@+id/tabbar"
       android:layout_width="match_parent"
       android:layout_height="match_parent"/>
   <com.jpeng.jptabbar.JPTabBar
       android:layout_alignParentBottom="true"
       android:id="@+id/tabbar"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:background="#fff"
       app:TabHeight="56dp"
       app:BadgeDraggable="true"
       app:TabAnimate="Jump"
       app:BadgePadding="4dp"
       app:BadgeMargin="5dp"
       app:BadgeTextSize="10dp"
       />
</RelativeLayout>

activity的java代码:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;

import com.jpeng.jptabbar.JPTabBar;
import com.jpeng.jptabbar.anno.NorIcons;
import com.jpeng.jptabbar.anno.SeleIcons;
import com.jpeng.jptabbar.anno.Titles;

import layout.HomeFragment;

public class MainActivity extends AppCompatActivity {

    private static final int ITEMPAGER = 4;
    private ViewPager mVp;
    private JPTabBar mTabBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         initView();

        ViewPagerAdapter adapter=new ViewPagerAdapter(getSupportFragmentManager());
        mVp.setAdapter(adapter);
        mTabBar.setContainer(mVp);
    }

    private void initView() {
        mVp = (ViewPager) findViewById(R.id.vp);
        mTabBar = (JPTabBar) findViewById(R.id.tabbar);
    }

    //设置标题
    @Titles
    private static final String[] mTitles={"微信","通讯录","发现",""};

    //设置选中图标
    @SeleIcons
    private static final int[] mSelectIcons={R.mipmap.al_,R.mipmap.al8,R.mipmap.alb,R.mipmap.ald};

    //设置未选中图标
    @NorIcons
    private static final int[] mNormalIcon={R.mipmap.ala,R.mipmap.al9,R.mipmap.alc,R.mipmap.ale};

    //Fragment适配器
    private class ViewPagerAdapter extends FragmentStatePagerAdapter{

        public ViewPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            Bundle bundle=new Bundle();
            bundle.putInt("position",position+1);
            HomeFragment fragment = new HomeFragment();
            fragment.setArguments(bundle);
            return fragment;
        }

        @Override
        public int getCount() {
            return ITEMPAGER;
        }
    }
}

Fragment Java代码:

public class HomeFragment extends Fragment {


    public HomeFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_home, container, false);
        initView(view);
        return view;
    }

    private void initView(View view) {
        TextView tvShow = (TextView) view.findViewById(R.id.tvShow);
        Bundle bundle = getArguments();
        int position = bundle.getInt("position");
        tvShow.setText(""+position+"Fragment");
    }

}

Fragment Xml代码:

<FrameLayout 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="layout.HomeFragment">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="25sp"
        android:id="@+id/tvShow"
        android:text="@string/hello_blank_fragment" />

</FrameLayout>

效果图:



2019-03-07 15:10:36 qq_41334474 阅读数 91
  • Android 项目实战-影讯

    本课程包含14个小节课程,内容包括:影讯项目演示,影讯项目架构,使用聚合API后台,封装Volley网络框架,根据JSON格式创建JavaBean,实现底部导航 ,实现侧滑菜单,实现MovieDao,实现可索引ListView,集成百度地图实现定位,实现首页电影列表,实现电影详情,实现影院列表,实现影院详细。

    6649 人正在学习 去看看 郭宏志
implementation 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar'

activity_main.xml :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/frame_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <com.flyco.tablayout.CommonTabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:layout_alignParentBottom="true"
        android:background="#fff"
        app:tl_iconHeight="20dp"
        app:tl_iconVisible="true"
        app:tl_iconWidth="20dp"
        app:tl_indicator_anim_duration="2"
        app:tl_indicator_anim_enable="true"
        app:tl_indicator_bounce_enable="true"
        app:tl_textSelectColor="#FF3333"
        app:tl_textUnselectColor="#666666"
        app:tl_textsize="12sp" />

</RelativeLayout>

MainActivity.java :

 

package com.example.myapplication6;

import android.content.Intent;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.flyco.tablayout.CommonTabLayout;
import com.flyco.tablayout.listener.CustomTabEntity;
import com.flyco.tablayout.listener.OnTabSelectListener;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity implements OnTabSelectListener {
    private FragmentManager mFragmentManager;
    private Fragment fragment_shouye,fragment_fenlei,fragment_zixun,fragment_wode;
    private FragmentTransaction fragmentTransaction;
    ArrayList<CustomTabEntity> tabs = new ArrayList<>();
    String [] titles={"首页","消息","进货单","我的"};
    int []  icons_f={R.drawable.ic_icon__shouye,R.drawable.ic_icon__shouye,R.drawable.ic_icon__shouye,R.drawable.ic_icon__shouye};
    int []  icons={R.drawable.ic_icon_shouye_f,R.drawable.ic_icon_shouye_f,R.drawable.ic_icon_shouye_f,R.drawable.ic_icon_shouye_f};


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mFragmentManager=getSupportFragmentManager();
        fragmentTransaction=mFragmentManager.beginTransaction();
        hideAllFragment(fragmentTransaction);
        //默认为首页
        if (fragment_shouye==null){
            fragment_shouye=new OneFragment();
            fragmentTransaction.add(R.id.frame_layout,fragment_shouye);
        }else {
            fragmentTransaction.show(fragment_shouye);
        }
        fragmentTransaction.commit();
        //init();

        for (int i=0;i<4;i++){
            MainTabEntity mainTabEntity = new MainTabEntity(titles[i],icons[i],icons_f[i]);
            tabs.add(mainTabEntity);
        }

        CommonTabLayout commonTabLayout = findViewById(R.id.tab_layout);
        commonTabLayout.setTabData(tabs);
        commonTabLayout.setOnTabSelectListener(this);


        int backStackCount = getFragmentManager().getBackStackEntryCount();
        for(int i = 0; i < backStackCount; i++) {
            getFragmentManager().popBackStack();
        }
    }
    @Override
    public void onTabSelect(int position) {
        FragmentTransaction fTransaction1 = mFragmentManager.beginTransaction();
        hideAllFragment(fTransaction1);
        switch (position){
            case 0:
                if (fragment_shouye==null){
                    fragment_shouye=new OneFragment();
                    fTransaction1.add(R.id.frame_layout,fragment_shouye);
                }else {
                    fTransaction1.show(fragment_shouye);
                }
                break;
            case 1:
                if (fragment_fenlei==null){
                    fragment_fenlei=new TwoFragment();
                    fTransaction1.add(R.id.frame_layout,fragment_fenlei);
                }else {
                    fTransaction1.show(fragment_fenlei);
                }
                break;
            case 2:
                if (fragment_zixun==null){
                    fragment_zixun=new ThreeFragment();
                    fTransaction1.add(R.id.frame_layout,fragment_zixun);
                }else {
                    fTransaction1.show(fragment_zixun);
                }
                break;
            case 3:
                if (fragment_wode==null){
                    fragment_wode=new FourFragment();
                    fTransaction1.add(R.id.frame_layout,fragment_wode);
                }else {
                    fTransaction1.show(fragment_wode);
                }
                break;

        }
        fTransaction1.commit();
    }

    @Override
    public void onTabReselect(int position) {

    }

    //隐藏所有Fragment
    private void hideAllFragment(FragmentTransaction fragmentTransaction){
        if(fragment_shouye != null)fragmentTransaction.hide(fragment_shouye);
        if(fragment_fenlei != null)fragmentTransaction.hide(fragment_fenlei);
        if(fragment_zixun != null)fragmentTransaction.hide(fragment_zixun);
        if(fragment_wode != null)fragmentTransaction.hide(fragment_wode);
    }


}

 

 

MainTabEntity.java :
package com.example.myapplication6;


import com.flyco.tablayout.listener.CustomTabEntity;

/**
 * Created by 5499 on 2018/10/17.
 */

public class MainTabEntity implements CustomTabEntity {
    String title;
    int selectedIcon;
    int unSelectIcon;


    public MainTabEntity(String title, int selectedIcon, int unSelectIcon) {
        this.title = title;
        this.selectedIcon = selectedIcon;
        this.unSelectIcon = unSelectIcon;
    }

    @Override
    public String getTabTitle() {
        return title;
    }

    @Override
    public int getTabSelectedIcon() {
        return selectedIcon;
    }

    @Override
    public int getTabUnselectedIcon() {
        return unSelectIcon;
    }
}

 

 

以前用过的一种方式。

2018-04-25 16:21:22 shaoyezhangliwei 阅读数 2336
  • Android 项目实战-影讯

    本课程包含14个小节课程,内容包括:影讯项目演示,影讯项目架构,使用聚合API后台,封装Volley网络框架,根据JSON格式创建JavaBean,实现底部导航 ,实现侧滑菜单,实现MovieDao,实现可索引ListView,集成百度地图实现定位,实现首页电影列表,实现电影详情,实现影院列表,实现影院详细。

    6649 人正在学习 去看看 郭宏志

大家在开发项目的时候,如果新开发一个app,采用这种标签栏模式的产品,需要搭建底部菜单。

实现起来很简单,而且可以有消息提醒功能。话不多说,直接上代码:

核心的CommonTabLayout  自定义的FrameLayout

package com.example.commontablayoutdemo;

import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;


import java.util.ArrayList;

/** 没有继承HorizontalScrollView不能滑动,对于ViewPager无依赖 */
@SuppressLint("NewApi")
public class CommonTabLayout extends FrameLayout implements ValueAnimator.AnimatorUpdateListener {
    private Context mContext;
    private ArrayList<CustomTabEntity> mTabEntitys = new ArrayList<>();
    private LinearLayout mTabsContainer;
    private int mCurrentTab;
    private int mLastTab;
    private int mTabCount;
    /** 用于绘制显示器 */
    private Rect mIndicatorRect = new Rect();
    private GradientDrawable mIndicatorDrawable = new GradientDrawable();

    private Paint mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint mDividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint mTrianglePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Path mTrianglePath = new Path();
    private static final int STYLE_NORMAL = 0;
    private static final int STYLE_TRIANGLE = 1;
    private static final int STYLE_BLOCK = 2;
    private int mIndicatorStyle = STYLE_NORMAL;

    private float mTabPadding;
    private boolean mTabSpaceEqual;
    private float mTabWidth;

    /** indicator */
    private int mIndicatorColor;
    private float mIndicatorHeight;
    private float mIndicatorWidth;
    private float mIndicatorCornerRadius;
    private float mIndicatorMarginLeft;
    private float mIndicatorMarginTop;
    private float mIndicatorMarginRight;
    private float mIndicatorMarginBottom;
    private long mIndicatorAnimDuration;
    private boolean mIndicatorAnimEnable;
    private boolean mIndicatorBounceEnable;
    private int mIndicatorGravity;

    /** underline */
    private int mUnderlineColor;
    private float mUnderlineHeight;
    private int mUnderlineGravity;

    /** divider */
    private int mDividerColor;
    private float mDividerWidth;
    private float mDividerPadding;

    /** title */
    private static final int TEXT_BOLD_NONE = 0;
    private static final int TEXT_BOLD_WHEN_SELECT = 1;
    private static final int TEXT_BOLD_BOTH = 2;
    private float mTextsize;
    private int mTextSelectColor;
    private int mTextUnselectColor;
    private int mTextBold;
    private boolean mTextAllCaps;

    /** icon */
    private boolean mIconVisible;
    private int mIconGravity;
    private float mIconWidth;
    private float mIconHeight;
    private float mIconMargin;

    private int mHeight;

    /** anim */
    private ValueAnimator mValueAnimator;
    private OvershootInterpolator mInterpolator = new OvershootInterpolator(1.5f);

    private FragmentChangeManager mFragmentChangeManager;

    public CommonTabLayout(Context context) {
        this(context, null, 0);
    }

    public CommonTabLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    @SuppressLint("NewApi")
	public CommonTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setWillNotDraw(false);//重写onDraw方法,需要调用这个方法来清除flag
        setClipChildren(false);
        setClipToPadding(false);

        this.mContext = context;
        mTabsContainer = new LinearLayout(context);
        addView(mTabsContainer);

        obtainAttributes(context, attrs);

        //get layout_height
        String height = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_height");

        //create ViewPager
        if (height.equals(ViewGroup.LayoutParams.MATCH_PARENT + "")) {
        } else if (height.equals(ViewGroup.LayoutParams.WRAP_CONTENT + "")) {
        } else {
            int[] systemAttrs = {android.R.attr.layout_height};
            TypedArray a = context.obtainStyledAttributes(attrs, systemAttrs);
            mHeight = a.getDimensionPixelSize(0, ViewGroup.LayoutParams.WRAP_CONTENT);
            a.recycle();
        }

        mValueAnimator = ValueAnimator.ofObject(new PointEvaluator(), mLastP, mCurrentP);
        mValueAnimator.addUpdateListener(this);
    }

    private void obtainAttributes(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CommonTabLayout);

        mIndicatorStyle = ta.getInt(R.styleable.CommonTabLayout_tl_indicator_style, 0);
        mIndicatorColor = ta.getColor(R.styleable.CommonTabLayout_tl_indicator_color, Color.parseColor(mIndicatorStyle == STYLE_BLOCK ? "#4B6A87" : "#ffffff"));
        mIndicatorHeight = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_height,
                dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 4 : (mIndicatorStyle == STYLE_BLOCK ? -1 : 2)));
        mIndicatorWidth = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_width, dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 10 : -1));
        mIndicatorCornerRadius = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_corner_radius, dp2px(mIndicatorStyle == STYLE_BLOCK ? -1 : 0));
        mIndicatorMarginLeft = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_margin_left, dp2px(0));
        mIndicatorMarginTop = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_margin_top, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0));
        mIndicatorMarginRight = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_margin_right, dp2px(0));
        mIndicatorMarginBottom = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_margin_bottom, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0));
        mIndicatorAnimEnable = ta.getBoolean(R.styleable.CommonTabLayout_tl_indicator_anim_enable, true);
        mIndicatorBounceEnable = ta.getBoolean(R.styleable.CommonTabLayout_tl_indicator_bounce_enable, true);
        mIndicatorAnimDuration = ta.getInt(R.styleable.CommonTabLayout_tl_indicator_anim_duration, -1);
        mIndicatorGravity = ta.getInt(R.styleable.CommonTabLayout_tl_indicator_gravity, Gravity.BOTTOM);

        mUnderlineColor = ta.getColor(R.styleable.CommonTabLayout_tl_underline_color, Color.parseColor("#ffffff"));
        mUnderlineHeight = ta.getDimension(R.styleable.CommonTabLayout_tl_underline_height, dp2px(0));
        mUnderlineGravity = ta.getInt(R.styleable.CommonTabLayout_tl_underline_gravity, Gravity.BOTTOM);

        mDividerColor = ta.getColor(R.styleable.CommonTabLayout_tl_divider_color, Color.parseColor("#ffffff"));
        mDividerWidth = ta.getDimension(R.styleable.CommonTabLayout_tl_divider_width, dp2px(0));
        mDividerPadding = ta.getDimension(R.styleable.CommonTabLayout_tl_divider_padding, dp2px(12));

        mTextsize = ta.getDimension(R.styleable.CommonTabLayout_tl_textsize, sp2px(13f));
        mTextSelectColor = ta.getColor(R.styleable.CommonTabLayout_tl_textSelectColor, Color.parseColor("#ffffff"));
        mTextUnselectColor = ta.getColor(R.styleable.CommonTabLayout_tl_textUnselectColor, Color.parseColor("#AAffffff"));
        mTextBold = ta.getInt(R.styleable.CommonTabLayout_tl_textBold, TEXT_BOLD_NONE);
        mTextAllCaps = ta.getBoolean(R.styleable.CommonTabLayout_tl_textAllCaps, false);

        mIconVisible = ta.getBoolean(R.styleable.CommonTabLayout_tl_iconVisible, true);
        mIconGravity = ta.getInt(R.styleable.CommonTabLayout_tl_iconGravity, Gravity.TOP);
        mIconWidth = ta.getDimension(R.styleable.CommonTabLayout_tl_iconWidth, dp2px(0));
        mIconHeight = ta.getDimension(R.styleable.CommonTabLayout_tl_iconHeight, dp2px(0));
        mIconMargin = ta.getDimension(R.styleable.CommonTabLayout_tl_iconMargin, dp2px(2.5f));

        mTabSpaceEqual = ta.getBoolean(R.styleable.CommonTabLayout_tl_tab_space_equal, true);
        mTabWidth = ta.getDimension(R.styleable.CommonTabLayout_tl_tab_width, dp2px(-1));
        mTabPadding = ta.getDimension(R.styleable.CommonTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? dp2px(0) : dp2px(10));

        ta.recycle();
    }

    public void setTabData(ArrayList<CustomTabEntity> tabEntitys) {
        if (tabEntitys == null || tabEntitys.size() == 0) {
            throw new IllegalStateException("TabEntitys can not be NULL or EMPTY !");
        }

        this.mTabEntitys.clear();
        this.mTabEntitys.addAll(tabEntitys);

        notifyDataSetChanged();
    }

    /** 关联数据支持同时切换fragments */
    public void setTabData(ArrayList<CustomTabEntity> tabEntitys, FragmentActivity fa, int containerViewId, ArrayList<Fragment> fragments) {
        mFragmentChangeManager = new FragmentChangeManager(fa.getSupportFragmentManager(), containerViewId, fragments);
        setTabData(tabEntitys);
    }

    /** 更新数据 */
    public void notifyDataSetChanged() {
        mTabsContainer.removeAllViews();
        this.mTabCount = mTabEntitys.size();
        View tabView;
        for (int i = 0; i < mTabCount; i++) {
            if (mIconGravity == Gravity.LEFT) {
                tabView = View.inflate(mContext, R.layout.layout_tab_left, null);
            } else if (mIconGravity == Gravity.RIGHT) {
                tabView = View.inflate(mContext, R.layout.layout_tab_right, null);
            } else if (mIconGravity == Gravity.BOTTOM) {
                tabView = View.inflate(mContext, R.layout.layout_tab_bottom, null);
            } else {
                tabView = View.inflate(mContext, R.layout.layout_tab_top, null);
            }

            tabView.setTag(i);
            addTab(i, tabView);
        }

        updateTabStyles();
    }

    /** 创建并添加tab */
    private void addTab(final int position, View tabView) {
        TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
        tv_tab_title.setText(mTabEntitys.get(position).getTabTitle());
        ImageView iv_tab_icon = (ImageView) tabView.findViewById(R.id.iv_tab_icon);
        iv_tab_icon.setImageResource(mTabEntitys.get(position).getTabUnselectedIcon());

        tabView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = (Integer) v.getTag();
                if (mCurrentTab != position) {
                    setCurrentTab(position);
                    if (mListener != null) {
                        mListener.onTabSelect(position);
                    }
                } else {
                    if (mListener != null) {
                        mListener.onTabReselect(position);
                    }
                }
            }
        });

        /** 每一个Tab的布局参数 */
        LinearLayout.LayoutParams lp_tab = mTabSpaceEqual ?
                new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f) :
                new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        if (mTabWidth > 0) {
            lp_tab = new LinearLayout.LayoutParams((int) mTabWidth, LayoutParams.MATCH_PARENT);
        }
        mTabsContainer.addView(tabView, position, lp_tab);
    }

    private void updateTabStyles() {
        for (int i = 0; i < mTabCount; i++) {
            View tabView = mTabsContainer.getChildAt(i);
            tabView.setPadding((int) mTabPadding, 0, (int) mTabPadding, 0);
            TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
            tv_tab_title.setTextColor(i == mCurrentTab ? mTextSelectColor : mTextUnselectColor);
            tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextsize);
//            tv_tab_title.setPadding((int) mTabPadding, 0, (int) mTabPadding, 0);
            if (mTextAllCaps) {
                tv_tab_title.setText(tv_tab_title.getText().toString().toUpperCase());
            }

            if (mTextBold == TEXT_BOLD_BOTH) {
                tv_tab_title.getPaint().setFakeBoldText(true);
            } else if (mTextBold == TEXT_BOLD_NONE) {
                tv_tab_title.getPaint().setFakeBoldText(false);
            }

            ImageView iv_tab_icon = (ImageView) tabView.findViewById(R.id.iv_tab_icon);
            if (mIconVisible) {
                iv_tab_icon.setVisibility(View.VISIBLE);
                CustomTabEntity tabEntity = mTabEntitys.get(i);
                iv_tab_icon.setImageResource(i == mCurrentTab ? tabEntity.getTabSelectedIcon() : tabEntity.getTabUnselectedIcon());
                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                        mIconWidth <= 0 ? LinearLayout.LayoutParams.WRAP_CONTENT : (int) mIconWidth,
                        mIconHeight <= 0 ? LinearLayout.LayoutParams.WRAP_CONTENT : (int) mIconHeight);
                if (mIconGravity == Gravity.LEFT) {
                    lp.rightMargin = (int) mIconMargin;
                } else if (mIconGravity == Gravity.RIGHT) {
                    lp.leftMargin = (int) mIconMargin;
                } else if (mIconGravity == Gravity.BOTTOM) {
                    lp.topMargin = (int) mIconMargin;
                } else {
                    lp.bottomMargin = (int) mIconMargin;
                }

                iv_tab_icon.setLayoutParams(lp);
            } else {
                iv_tab_icon.setVisibility(View.GONE);
            }
        }
    }

    private void updateTabSelection(int position) {
        for (int i = 0; i < mTabCount; ++i) {
            View tabView = mTabsContainer.getChildAt(i);
            final boolean isSelect = i == position;
            TextView tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
            tab_title.setTextColor(isSelect ? mTextSelectColor : mTextUnselectColor);
            ImageView iv_tab_icon = (ImageView) tabView.findViewById(R.id.iv_tab_icon);
            CustomTabEntity tabEntity = mTabEntitys.get(i);
            iv_tab_icon.setImageResource(isSelect ? tabEntity.getTabSelectedIcon() : tabEntity.getTabUnselectedIcon());
            if (mTextBold == TEXT_BOLD_WHEN_SELECT) {
                tab_title.getPaint().setFakeBoldText(isSelect);
            }
        }
    }

    private void calcOffset() {
        final View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab);
        mCurrentP.left = currentTabView.getLeft();
        mCurrentP.right = currentTabView.getRight();

        final View lastTabView = mTabsContainer.getChildAt(this.mLastTab);
        mLastP.left = lastTabView.getLeft();
        mLastP.right = lastTabView.getRight();

//        Log.d("AAA", "mLastP--->" + mLastP.left + "&" + mLastP.right);
//        Log.d("AAA", "mCurrentP--->" + mCurrentP.left + "&" + mCurrentP.right);
        if (mLastP.left == mCurrentP.left && mLastP.right == mCurrentP.right) {
            invalidate();
        } else {
            mValueAnimator.setObjectValues(mLastP, mCurrentP);
            if (mIndicatorBounceEnable) {
                mValueAnimator.setInterpolator(mInterpolator);
            }

            if (mIndicatorAnimDuration < 0) {
                mIndicatorAnimDuration = mIndicatorBounceEnable ? 500 : 250;
            }
            mValueAnimator.setDuration(mIndicatorAnimDuration);
            mValueAnimator.start();
        }
    }

    private void calcIndicatorRect() {
        View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab);
        float left = currentTabView.getLeft();
        float right = currentTabView.getRight();

        mIndicatorRect.left = (int) left;
        mIndicatorRect.right = (int) right;

        if (mIndicatorWidth < 0) {   //indicatorWidth小于0时,原jpardogo's PagerSlidingTabStrip

        } else {//indicatorWidth大于0时,圆角矩形以及三角形
            float indicatorLeft = currentTabView.getLeft() + (currentTabView.getWidth() - mIndicatorWidth) / 2;

            mIndicatorRect.left = (int) indicatorLeft;
            mIndicatorRect.right = (int) (mIndicatorRect.left + mIndicatorWidth);
        }
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab);
        IndicatorPoint p = (IndicatorPoint) animation.getAnimatedValue();
        mIndicatorRect.left = (int) p.left;
        mIndicatorRect.right = (int) p.right;

        if (mIndicatorWidth < 0) {   //indicatorWidth小于0时,原jpardogo's PagerSlidingTabStrip

        } else {//indicatorWidth大于0时,圆角矩形以及三角形
            float indicatorLeft = p.left + (currentTabView.getWidth() - mIndicatorWidth) / 2;

            mIndicatorRect.left = (int) indicatorLeft;
            mIndicatorRect.right = (int) (mIndicatorRect.left + mIndicatorWidth);
        }
        invalidate();
    }

    private boolean mIsFirstDraw = true;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (isInEditMode() || mTabCount <= 0) {
            return;
        }

        int height = getHeight();
        int paddingLeft = getPaddingLeft();
        // draw divider
        if (mDividerWidth > 0) {
            mDividerPaint.setStrokeWidth(mDividerWidth);
            mDividerPaint.setColor(mDividerColor);
            for (int i = 0; i < mTabCount - 1; i++) {
                View tab = mTabsContainer.getChildAt(i);
                canvas.drawLine(paddingLeft + tab.getRight(), mDividerPadding, paddingLeft + tab.getRight(), height - mDividerPadding, mDividerPaint);
            }
        }

        // draw underline
        if (mUnderlineHeight > 0) {
            mRectPaint.setColor(mUnderlineColor);
            if (mUnderlineGravity == Gravity.BOTTOM) {
                canvas.drawRect(paddingLeft, height - mUnderlineHeight, mTabsContainer.getWidth() + paddingLeft, height, mRectPaint);
            } else {
                canvas.drawRect(paddingLeft, 0, mTabsContainer.getWidth() + paddingLeft, mUnderlineHeight, mRectPaint);
            }
        }

        //draw indicator line
        if (mIndicatorAnimEnable) {
            if (mIsFirstDraw) {
                mIsFirstDraw = false;
                calcIndicatorRect();
            }
        } else {
            calcIndicatorRect();
        }


        if (mIndicatorStyle == STYLE_TRIANGLE) {
            if (mIndicatorHeight > 0) {
                mTrianglePaint.setColor(mIndicatorColor);
                mTrianglePath.reset();
                mTrianglePath.moveTo(paddingLeft + mIndicatorRect.left, height);
                mTrianglePath.lineTo(paddingLeft + mIndicatorRect.left / 2 + mIndicatorRect.right / 2, height - mIndicatorHeight);
                mTrianglePath.lineTo(paddingLeft + mIndicatorRect.right, height);
                mTrianglePath.close();
                canvas.drawPath(mTrianglePath, mTrianglePaint);
            }
        } else if (mIndicatorStyle == STYLE_BLOCK) {
            if (mIndicatorHeight < 0) {
                mIndicatorHeight = height - mIndicatorMarginTop - mIndicatorMarginBottom;
            } else {

            }

            if (mIndicatorHeight > 0) {
                if (mIndicatorCornerRadius < 0 || mIndicatorCornerRadius > mIndicatorHeight / 2) {
                    mIndicatorCornerRadius = mIndicatorHeight / 2;
                }

                mIndicatorDrawable.setColor(mIndicatorColor);
                mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left,
                        (int) mIndicatorMarginTop, (int) (paddingLeft + mIndicatorRect.right - mIndicatorMarginRight),
                        (int) (mIndicatorMarginTop + mIndicatorHeight));
                mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius);
                mIndicatorDrawable.draw(canvas);
            }
        } else {
               /* mRectPaint.setColor(mIndicatorColor);
                calcIndicatorRect();
                canvas.drawRect(getPaddingLeft() + mIndicatorRect.left, getHeight() - mIndicatorHeight,
                        mIndicatorRect.right + getPaddingLeft(), getHeight(), mRectPaint);*/

            if (mIndicatorHeight > 0) {
                mIndicatorDrawable.setColor(mIndicatorColor);
                if (mIndicatorGravity == Gravity.BOTTOM) {
                    mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left,
                            height - (int) mIndicatorHeight - (int) mIndicatorMarginBottom,
                            paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight,
                            height - (int) mIndicatorMarginBottom);
                } else {
                    mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left,
                            (int) mIndicatorMarginTop,
                            paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight,
                            (int) mIndicatorHeight + (int) mIndicatorMarginTop);
                }
                mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius);
                mIndicatorDrawable.draw(canvas);
            }
        }
    }

    //setter and getter
    public void setCurrentTab(int currentTab) {
        mLastTab = this.mCurrentTab;
        this.mCurrentTab = currentTab;
        updateTabSelection(currentTab);
        if (mFragmentChangeManager != null) {
            mFragmentChangeManager.setFragments(currentTab);
        }
        if (mIndicatorAnimEnable) {
            calcOffset();
        } else {
            invalidate();
        }
    }

    public void setIndicatorStyle(int indicatorStyle) {
        this.mIndicatorStyle = indicatorStyle;
        invalidate();
    }

    public void setTabPadding(float tabPadding) {
        this.mTabPadding = dp2px(tabPadding);
        updateTabStyles();
    }

    public void setTabSpaceEqual(boolean tabSpaceEqual) {
        this.mTabSpaceEqual = tabSpaceEqual;
        updateTabStyles();
    }

    public void setTabWidth(float tabWidth) {
        this.mTabWidth = dp2px(tabWidth);
        updateTabStyles();
    }

    public void setIndicatorColor(int indicatorColor) {
        this.mIndicatorColor = indicatorColor;
        invalidate();
    }

    public void setIndicatorHeight(float indicatorHeight) {
        this.mIndicatorHeight = dp2px(indicatorHeight);
        invalidate();
    }

    public void setIndicatorWidth(float indicatorWidth) {
        this.mIndicatorWidth = dp2px(indicatorWidth);
        invalidate();
    }

    public void setIndicatorCornerRadius(float indicatorCornerRadius) {
        this.mIndicatorCornerRadius = dp2px(indicatorCornerRadius);
        invalidate();
    }

    public void setIndicatorGravity(int indicatorGravity) {
        this.mIndicatorGravity = indicatorGravity;
        invalidate();
    }

    public void setIndicatorMargin(float indicatorMarginLeft, float indicatorMarginTop,
                                   float indicatorMarginRight, float indicatorMarginBottom) {
        this.mIndicatorMarginLeft = dp2px(indicatorMarginLeft);
        this.mIndicatorMarginTop = dp2px(indicatorMarginTop);
        this.mIndicatorMarginRight = dp2px(indicatorMarginRight);
        this.mIndicatorMarginBottom = dp2px(indicatorMarginBottom);
        invalidate();
    }

    public void setIndicatorAnimDuration(long indicatorAnimDuration) {
        this.mIndicatorAnimDuration = indicatorAnimDuration;
    }

    public void setIndicatorAnimEnable(boolean indicatorAnimEnable) {
        this.mIndicatorAnimEnable = indicatorAnimEnable;
    }

    public void setIndicatorBounceEnable(boolean indicatorBounceEnable) {
        this.mIndicatorBounceEnable = indicatorBounceEnable;
    }

    public void setUnderlineColor(int underlineColor) {
        this.mUnderlineColor = underlineColor;
        invalidate();
    }

    public void setUnderlineHeight(float underlineHeight) {
        this.mUnderlineHeight = dp2px(underlineHeight);
        invalidate();
    }

    public void setUnderlineGravity(int underlineGravity) {
        this.mUnderlineGravity = underlineGravity;
        invalidate();
    }

    public void setDividerColor(int dividerColor) {
        this.mDividerColor = dividerColor;
        invalidate();
    }

    public void setDividerWidth(float dividerWidth) {
        this.mDividerWidth = dp2px(dividerWidth);
        invalidate();
    }

    public void setDividerPadding(float dividerPadding) {
        this.mDividerPadding = dp2px(dividerPadding);
        invalidate();
    }

    public void setTextsize(float textsize) {
        this.mTextsize = sp2px(textsize);
        updateTabStyles();
    }

    public void setTextSelectColor(int textSelectColor) {
        this.mTextSelectColor = textSelectColor;
        updateTabStyles();
    }

    public void setTextUnselectColor(int textUnselectColor) {
        this.mTextUnselectColor = textUnselectColor;
        updateTabStyles();
    }

    public void setTextBold(int textBold) {
        this.mTextBold = textBold;
        updateTabStyles();
    }

    public void setIconVisible(boolean iconVisible) {
        this.mIconVisible = iconVisible;
        updateTabStyles();
    }

    public void setIconGravity(int iconGravity) {
        this.mIconGravity = iconGravity;
        notifyDataSetChanged();
    }

    public void setIconWidth(float iconWidth) {
        this.mIconWidth = dp2px(iconWidth);
        updateTabStyles();
    }

    public void setIconHeight(float iconHeight) {
        this.mIconHeight = dp2px(iconHeight);
        updateTabStyles();
    }

    public void setIconMargin(float iconMargin) {
        this.mIconMargin = dp2px(iconMargin);
        updateTabStyles();
    }

    public void setTextAllCaps(boolean textAllCaps) {
        this.mTextAllCaps = textAllCaps;
        updateTabStyles();
    }


    public int getTabCount() {
        return mTabCount;
    }

    public int getCurrentTab() {
        return mCurrentTab;
    }

    public int getIndicatorStyle() {
        return mIndicatorStyle;
    }

    public float getTabPadding() {
        return mTabPadding;
    }

    public boolean isTabSpaceEqual() {
        return mTabSpaceEqual;
    }

    public float getTabWidth() {
        return mTabWidth;
    }

    public int getIndicatorColor() {
        return mIndicatorColor;
    }

    public float getIndicatorHeight() {
        return mIndicatorHeight;
    }

    public float getIndicatorWidth() {
        return mIndicatorWidth;
    }

    public float getIndicatorCornerRadius() {
        return mIndicatorCornerRadius;
    }

    public float getIndicatorMarginLeft() {
        return mIndicatorMarginLeft;
    }

    public float getIndicatorMarginTop() {
        return mIndicatorMarginTop;
    }

    public float getIndicatorMarginRight() {
        return mIndicatorMarginRight;
    }

    public float getIndicatorMarginBottom() {
        return mIndicatorMarginBottom;
    }

    public long getIndicatorAnimDuration() {
        return mIndicatorAnimDuration;
    }

    public boolean isIndicatorAnimEnable() {
        return mIndicatorAnimEnable;
    }

    public boolean isIndicatorBounceEnable() {
        return mIndicatorBounceEnable;
    }

    public int getUnderlineColor() {
        return mUnderlineColor;
    }

    public float getUnderlineHeight() {
        return mUnderlineHeight;
    }

    public int getDividerColor() {
        return mDividerColor;
    }

    public float getDividerWidth() {
        return mDividerWidth;
    }

    public float getDividerPadding() {
        return mDividerPadding;
    }

    public float getTextsize() {
        return mTextsize;
    }

    public int getTextSelectColor() {
        return mTextSelectColor;
    }

    public int getTextUnselectColor() {
        return mTextUnselectColor;
    }

    public int getTextBold() {
        return mTextBold;
    }

    public boolean isTextAllCaps() {
        return mTextAllCaps;
    }

    public int getIconGravity() {
        return mIconGravity;
    }

    public float getIconWidth() {
        return mIconWidth;
    }

    public float getIconHeight() {
        return mIconHeight;
    }

    public float getIconMargin() {
        return mIconMargin;
    }

    public boolean isIconVisible() {
        return mIconVisible;
    }


    public ImageView getIconView(int tab) {
        View tabView = mTabsContainer.getChildAt(tab);
        ImageView iv_tab_icon = (ImageView) tabView.findViewById(R.id.iv_tab_icon);
        return iv_tab_icon;
    }

    public TextView getTitleView(int tab) {
        View tabView = mTabsContainer.getChildAt(tab);
        TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
        return tv_tab_title;
    }

    //setter and getter

    // show MsgTipView
    private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private SparseArray<Boolean> mInitSetMap = new SparseArray<>();

    /**
     * 显示未读消息
     *
     * @param position 显示tab位置
     * @param num      num小于等于0显示红点,num大于0显示数字
     */
    public void showMsg(int position, int num) {
        if (position >= mTabCount) {
            position = mTabCount - 1;
        }

        View tabView = mTabsContainer.getChildAt(position);
        MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip);
        if (tipView != null) {
            UnreadMsgUtils.show(tipView, num);

            if (mInitSetMap.get(position) != null && mInitSetMap.get(position)) {
                return;
            }

            if (!mIconVisible) {
                setMsgMargin(position, 2, 2);
            } else {
                setMsgMargin(position, 0,
                        mIconGravity == Gravity.LEFT || mIconGravity == Gravity.RIGHT ? 4 : 0);
            }

            mInitSetMap.put(position, true);
        }
    }

    /**
     * 显示未读红点
     *
     * @param position 显示tab位置
     */
    public void showDot(int position) {
        if (position >= mTabCount) {
            position = mTabCount - 1;
        }
        showMsg(position, 0);
    }

    public void hideMsg(int position) {
        if (position >= mTabCount) {
            position = mTabCount - 1;
        }

        View tabView = mTabsContainer.getChildAt(position);
        MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip);
        if (tipView != null) {
            tipView.setVisibility(View.GONE);
        }
    }

    /**
     * 设置提示红点偏移,注意
     * 1.控件为固定高度:参照点为tab内容的右上角
     * 2.控件高度不固定(WRAP_CONTENT):参照点为tab内容的右上角,此时高度已是红点的最高显示范围,所以这时bottomPadding其实就是topPadding
     */
    public void setMsgMargin(int position, float leftPadding, float bottomPadding) {
        if (position >= mTabCount) {
            position = mTabCount - 1;
        }
        View tabView = mTabsContainer.getChildAt(position);
        MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip);
        if (tipView != null) {
            TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
            mTextPaint.setTextSize(mTextsize);
            float textWidth = mTextPaint.measureText(tv_tab_title.getText().toString());
            float textHeight = mTextPaint.descent() - mTextPaint.ascent();
            MarginLayoutParams lp = (MarginLayoutParams) tipView.getLayoutParams();

            float iconH = mIconHeight;
            float margin = 0;
            if (mIconVisible) {
                if (iconH <= 0) {
                    iconH = mContext.getResources().getDrawable(mTabEntitys.get(position).getTabSelectedIcon()).getIntrinsicHeight();
                }
                margin = mIconMargin;
            }

            if (mIconGravity == Gravity.TOP || mIconGravity == Gravity.BOTTOM) {
                lp.leftMargin = dp2px(leftPadding);
                lp.topMargin = mHeight > 0 ? (int) (mHeight - textHeight - iconH - margin) / 2 - dp2px(bottomPadding) : dp2px(bottomPadding);
            } else {
                lp.leftMargin = dp2px(leftPadding);
                lp.topMargin = mHeight > 0 ? (int) (mHeight - Math.max(textHeight, iconH)) / 2 - dp2px(bottomPadding) : dp2px(bottomPadding);
            }

            tipView.setLayoutParams(lp);
        }
    }

    /** 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 */
    public MsgView getMsgView(int position) {
        if (position >= mTabCount) {
            position = mTabCount - 1;
        }
        View tabView = mTabsContainer.getChildAt(position);
        MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip);
        return tipView;
    }

    private OnTabSelectListener mListener;

    public void setOnTabSelectListener(OnTabSelectListener listener) {
        this.mListener = listener;
    }


    @Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        bundle.putParcelable("instanceState", super.onSaveInstanceState());
        bundle.putInt("mCurrentTab", mCurrentTab);
        return bundle;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (state instanceof Bundle) {
            Bundle bundle = (Bundle) state;
            mCurrentTab = bundle.getInt("mCurrentTab");
            state = bundle.getParcelable("instanceState");
            if (mCurrentTab != 0 && mTabsContainer.getChildCount() > 0) {
                updateTabSelection(mCurrentTab);
            }
        }
        super.onRestoreInstanceState(state);
    }

    class IndicatorPoint {
        public float left;
        public float right;
    }

    private IndicatorPoint mCurrentP = new IndicatorPoint();
    private IndicatorPoint mLastP = new IndicatorPoint();

    class PointEvaluator implements TypeEvaluator<IndicatorPoint> {
        @Override
        public IndicatorPoint evaluate(float fraction, IndicatorPoint startValue, IndicatorPoint endValue) {
            float left = startValue.left + fraction * (endValue.left - startValue.left);
            float right = startValue.right + fraction * (endValue.right - startValue.right);
            IndicatorPoint point = new IndicatorPoint();
            point.left = left;
            point.right = right;
            return point;
        }
    }


    protected int dp2px(float dp) {
        final float scale = mContext.getResources().getDisplayMetrics().density;
        return (int) (dp * scale + 0.5f);
    }

    protected int sp2px(float sp) {
        final float scale = this.mContext.getResources().getDisplayMetrics().scaledDensity;
        return (int) (sp * scale + 0.5f);
    }

}

这个整体设计的代码太多,所以只贴出核心代码,但是为了方便大家,特意整理了

DEMO

大家如果有需要的可以直接下载,如果大家还有其他问题,欢迎加入我的qq群讨论交流:

开发一群:454430053开发二群:537532956

没有更多推荐了,返回首页