From cd13751df41c6504b3934cd3f1bd441c4ba172ff Mon Sep 17 00:00:00 2001 From: lmw <125975490@qq.com> Date: 星期五, 19 七月 2024 11:38:27 +0800 Subject: [PATCH] fix bug --- app/src/main/java/com/dollearn/student/ui/home/ChooseVoiceActivity.kt | 9 app/src/main/java/com/dollearn/student/network/Functions.kt | 5 app/src/main/java/com/dollearn/student/views/SlidingTabLayout.java | 923 +++++++++++++++++++++++++++++++++++ app/src/main/AndroidManifest.xml | 28 - app/src/main/java/com/dollearn/student/network/ApiService.kt | 55 -- app/src/main/res/layout/activity_schedul.xml | 4 app/src/main/java/com/dollearn/student/network/Apis.kt | 29 - app/src/main/java/com/dollearn/student/ui/mine/MineFragment.kt | 2 app/src/main/java/com/dollearn/student/ui/home/ScheduleActivity.kt | 29 app/src/main/res/layout/fragment_include.xml | 352 +++++++----- app/src/main/java/com/dollearn/student/ui/home/IncludeFragment.kt | 22 app/src/main/java/com/dollearn/student/ui/home/DailyFragment.kt | 3 app/src/main/java/com/dollearn/student/network/HttpManager.kt | 77 -- 13 files changed, 1,173 insertions(+), 365 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f28e9e8..94191a7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,36 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.dollearn.student"> - <!--用于进行网络定位--> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - <!--用于访问GPS定位--> - <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> - <!--用于获取运营商信息,用于支持提供运营商信息相关的接口--> - <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> - <!--用于访问wifi网络信息,wifi信息会用于进行网络定位--> - <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> - <!--用于获取wifi的获取权限,wifi信息会用来进行网络定位--> - <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!--用于访问网络,网络定位需要上网--> <uses-permission android:name="android.permission.INTERNET" /> <!--用于读取手机当前的状态--> - <uses-permission android:name="android.permission.READ_PHONE_STATE" /> - <!--用于写入缓存数据到扩展存储卡--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <!--用于申请调用A-GPS模块--> - <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> - <!--用于申请获取蓝牙信息进行室内定位--> - <uses-permission android:name="android.permission.BLUETOOTH" /> - <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> - <uses-permission android:name="android.permission.CAMERA" /> -<!-- 尝试申请全部文件管理权限--> - <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> - - <queries> - <package android:name="com.eg.android.AlipayGphone" /> - <package android:name="com.tencent.mm" /> - </queries> <application android:name=".DollearnApplication" @@ -79,9 +54,6 @@ android:label="自主学习5-音图相配" android:screenOrientation="landscape" /> - <activity - android:name=".ui.discovery.NoticeDetailActivity" - android:label="公告详情" /> <activity android:name=".ui.shop.GoodsDetailActivity" android:label="商品详情" /> diff --git a/app/src/main/java/com/dollearn/student/network/ApiService.kt b/app/src/main/java/com/dollearn/student/network/ApiService.kt index 950ccd1..26c040a 100644 --- a/app/src/main/java/com/dollearn/student/network/ApiService.kt +++ b/app/src/main/java/com/dollearn/student/network/ApiService.kt @@ -14,10 +14,6 @@ @POST(Apis.H5_URL) fun getH5(@Field("type") type: Int): Flowable<ResultData<String>> - @FormUrlEncoded - @POST(Apis.queryPhysical) - fun queryPhysical(@Field("stuID") id: String): Flowable<ResultData<Report>> - @GET(Apis.userDetails) fun userDetails(): Flowable<ResultData<UserBean>> @@ -26,32 +22,6 @@ @GET(Apis.studyRecord) fun studyRecord(): Flowable<ResultData<StudyRecord>> - - @FormUrlEncoded - @POST(Apis.stuComment) - fun stuComment( - @Field("stuId") stuId: String - ): Flowable<ResultData<ArrayList<Evaluation>>> - - @FormUrlEncoded - @POST(Apis.lessonDetails) - fun lessonDetails( - @Field("stuId") stuId: String, - @Field("lessonId") lessonId: String - ): Flowable<ResultData<MyCourseDetail>> - - @FormUrlEncoded - @POST(Apis.editDefault) - fun editDefault(@Field("stuId") stuId: String): Flowable<ResultData<Any>> - - @FormUrlEncoded - @POST(Apis.recordDetails) - fun recordDetails( - @Field("stuId") stuId: String, - @Field("lessionId") lessonId: String, - @Field("time") time: String?, - @Field("type") type: Int? - ): Flowable<ResultData<ArrayList<CourseRecord>>> @FormUrlEncoded @POST @@ -87,12 +57,6 @@ @GET(Apis.giveIntegral) fun giveIntegral(): Flowable<ResultData<Boolean>> - - @FormUrlEncoded - @POST(Apis.redemptionDetails) - fun redemptionDetails( - @Field("detailsId") goodId: String - ): Flowable<ResultData<ExchangeDetail>> @POST(Apis.cancellation) fun cancellation(): Flowable<ResultData<Any>> @@ -205,23 +169,4 @@ @GET(Apis.exchangeRecord) fun exchangeRecord(@Query("pageNumber") page:Int,@Query("pageSize") pageSize: Int = 30): Flowable<ResultData<ExchangeRecordBean>> - - @FormUrlEncoded - @POST(Apis.registeredData) - fun registeredData( - @Field("lat") lat: Double?, - @Field("lon") lon: Double?, - @Field("coursePayId") coursePayId: String, - @Field("orderId") orderId: String - ): Flowable<ResultData<JoinedCourse>> - @POST(Apis.noticeList) - fun noticeList(): Flowable<ResultData<List<Notice>>> - - @FormUrlEncoded - @POST - fun noticeDetail( - @Url url: String, - @Field("noId") noId: String, - @Field("quesId") quesId: String - ): Flowable<ResultData<Notice>> } \ No newline at end of file diff --git a/app/src/main/java/com/dollearn/student/network/Apis.kt b/app/src/main/java/com/dollearn/student/network/Apis.kt index 6aabc1c..98dace0 100644 --- a/app/src/main/java/com/dollearn/student/network/Apis.kt +++ b/app/src/main/java/com/dollearn/student/network/Apis.kt @@ -56,8 +56,8 @@ /** * 商城 */ - const val goodTypeStudy = "goods/base/goods/goodTypeStudy" //s品分类列表 - const val goodListStudy = "goods/base/goods/goodListStudy" //s品列表 + const val goodTypeStudy = "goods/base/goods/goodTypeStudy" //品分类列表 + const val goodListStudy = "goods/base/goods/goodListStudy" //品列表 const val goodDetail = "goods/base/goods/goodDetail" const val getIntegralStudy = "study/base/study/getIntegralStudy" const val redeemNow = "goods/base/goods/redeemNow" @@ -80,31 +80,6 @@ const val addressTree = "goods/base/goods/addressTree" const val addressDelete = "goods/base/goods/addressDelete" const val integralDetail = "study/base/study/integralDetail" - - - /** - * 运动营 - */ - const val lessonDetails = "account/api/startCource/lessonDetails" - const val editDefault = "account/api/startCource/editDefault" - const val recordDetails = "account/api/startCource/recordDetails" - const val stuComment = "account/api/startCource/stuComment" - const val registeredData = "course/api/startCource/RegisteredData" - const val queryPhysical = "account/api/startCource/queryPhysical" - - - /** - * 福利 - */ const val cancellation = "account/api/useBenefit/cancellation" - const val redemptionDetails = "account/api/useBenefit/redemptionDetails" - - - /** - * 探索玩湃 - */ - const val noticeList = "account/base/exploreWP/noticeList" - const val noticeDetail = "account/base/exploreWP/noticeDetail" - const val exceptionDetail = "account/base/exploreWP/exceptionDetail" } \ No newline at end of file diff --git a/app/src/main/java/com/dollearn/student/network/Functions.kt b/app/src/main/java/com/dollearn/student/network/Functions.kt index 4a2c68b..beb1119 100644 --- a/app/src/main/java/com/dollearn/student/network/Functions.kt +++ b/app/src/main/java/com/dollearn/student/network/Functions.kt @@ -6,6 +6,7 @@ import cn.sinata.xldutils.fragment.BaseFragment import cn.sinata.xldutils.rxutils.ResultDataSubscriber import cn.sinata.xldutils.utils.SPUtils +import cn.sinata.xldutils.utils.myToast import com.dollearn.student.DollearnApplication import com.dollearn.student.ui.login.LoginActivity import com.dollearn.student.utils.Const @@ -27,10 +28,10 @@ override fun onError(code: Int, msg: String) { if (code == 700||code == 600||code == 505||code == 401){//token无效 - error(code,"登录已失效,请重新登录") SPUtils.instance().remove(Const.User.TOKEN).remove(Const.User.USER_ID).apply() (activity.application as DollearnApplication).exit() activity.startActivity<LoginActivity>() + activity.myToast("登录失效,请重新登录") }else{ super.onError(code, msg) error(code,msg) @@ -53,7 +54,7 @@ override fun onError(code: Int, msg: String) { if (code == 700||code == 600||code == 505||code == 401){//token无效 - error(code,"登录已失效,请重新登录") + fragment.myToast("登录失效,请重新登录") SPUtils.instance().remove(Const.User.TOKEN).remove(Const.User.USER_ID).apply() (fragment.activity!!.application as DollearnApplication).exit() fragment.startActivity<LoginActivity>() diff --git a/app/src/main/java/com/dollearn/student/network/HttpManager.kt b/app/src/main/java/com/dollearn/student/network/HttpManager.kt index c968a51..1cf99f3 100644 --- a/app/src/main/java/com/dollearn/student/network/HttpManager.kt +++ b/app/src/main/java/com/dollearn/student/network/HttpManager.kt @@ -9,7 +9,6 @@ import io.reactivex.Flowable object HttpManager { - private const val PAGE_SIZE = 20 /** * 发起请求方法 @@ -23,14 +22,6 @@ */ fun getH5(type: Int): Flowable<ResultData<String>> { return request().getH5(type) - } - - - /** - * 体检报告 - */ - fun queryPhysical(id: String): Flowable<ResultData<Report>> { - return request().queryPhysical(id) } /** @@ -55,41 +46,6 @@ return request().studyRecord() } - - /** - * 获取课时记录 - */ - fun recordDetails( - stuId: String, - courseId: String, - time: String?, - type: Int? - ): Flowable<ResultData<ArrayList<CourseRecord>>> { - return request().recordDetails(stuId, courseId, time, type) - } - - - /** - * 评语 - */ - fun stuComment(id: String): Flowable<ResultData<ArrayList<Evaluation>>> { - return request().stuComment(id) - } - - - /** - * 课时详情 - */ - fun lessonDetails(id: String, stuId: String): Flowable<ResultData<MyCourseDetail>> { - return request().lessonDetails(stuId, id) - } - - /** - * 设为默认运动营成员 - */ - fun editDefault(stuId: String): Flowable<ResultData<Any>> { - return request().editDefault(stuId) - } /** * 获取验证码 @@ -202,13 +158,6 @@ */ fun teamSchedule(day: Int,week: Int,type: Int): Flowable<ResultData<ProgressBean>> { return request().teamSchedule(day, type, week) - } - - /** - * 兑换详情 - */ - fun redemptionDetails(id: String): Flowable<ResultData<ExchangeDetail>> { - return request().redemptionDetails(id) } /** @@ -399,31 +348,5 @@ */ fun exchangeRecord(page: Int): Flowable<ResultData<ExchangeRecordBean>> { return request().exchangeRecord(page) - } - - /** - * 已报运动营详情 - */ - fun registeredData(id: String,orderId: String): Flowable<ResultData<JoinedCourse>> { - return request().registeredData(DollearnApplication.lat,DollearnApplication.lon,id,orderId) - } - - - /** - * 公告列表 - */ - fun noticeList(): Flowable<ResultData<List<Notice>>> { - return request().noticeList() - } - - /** - * 公告详情 - */ - fun noticeDetail(id: String, type: Int): Flowable<ResultData<Notice>> { - return request().noticeDetail( - if (type == 1) Apis.noticeDetail else Apis.exceptionDetail, - id, - id - ) } } \ No newline at end of file diff --git a/app/src/main/java/com/dollearn/student/ui/home/ChooseVoiceActivity.kt b/app/src/main/java/com/dollearn/student/ui/home/ChooseVoiceActivity.kt index ba2d65e..a1a188e 100644 --- a/app/src/main/java/com/dollearn/student/ui/home/ChooseVoiceActivity.kt +++ b/app/src/main/java/com/dollearn/student/ui/home/ChooseVoiceActivity.kt @@ -61,9 +61,12 @@ ResultActivity.startResult(this,day,week,season,2,totalCount,rightCount,data!!.data.integral,time,data!!.data.id) finish() }else{ - (fragments[view_pager.currentItem+1] as ChooseVoiceFragment).recover() - view_pager.setCurrentItem(view_pager.currentItem+1,true) - tv_last.visible() + if (data!!.subjectList[view_pager.currentItem].filter { it.completed }.size == 4){ //防止多次调用触发 + (fragments[view_pager.currentItem+1] as ChooseVoiceFragment).recover() + view_pager.setCurrentItem(view_pager.currentItem+1,true) + tv_last.visible() + } + } } diff --git a/app/src/main/java/com/dollearn/student/ui/home/DailyFragment.kt b/app/src/main/java/com/dollearn/student/ui/home/DailyFragment.kt index 45b33db..844eee2 100644 --- a/app/src/main/java/com/dollearn/student/ui/home/DailyFragment.kt +++ b/app/src/main/java/com/dollearn/student/ui/home/DailyFragment.kt @@ -180,7 +180,6 @@ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - if (resultCode == Activity.RESULT_OK) - getProgress() + getProgress() } } diff --git a/app/src/main/java/com/dollearn/student/ui/home/IncludeFragment.kt b/app/src/main/java/com/dollearn/student/ui/home/IncludeFragment.kt index c244512..320c3ea 100644 --- a/app/src/main/java/com/dollearn/student/ui/home/IncludeFragment.kt +++ b/app/src/main/java/com/dollearn/student/ui/home/IncludeFragment.kt @@ -48,7 +48,7 @@ private val act by lazy { requireActivity() as IncludeActivity } private var voiceIndex = -1 //点击播放的声音序号 0-5取值 - private val voiceViews by lazy { arrayListOf(cl_voice1,cl_voice2,cl_voice3,cl_voice4,cl_voice5,cl_voice6) } + private val voiceViews by lazy { arrayListOf(cl_voice1_real,cl_voice2_real,cl_voice3_real,cl_voice4_real,cl_voice5_real,cl_voice6_real) } private var playing = false private val answerImg = arrayListOf<String>() //随机答案图片 @@ -87,13 +87,23 @@ } data?.apply { val originList = subjectList[group] - iv_1.setImageURI(originList[0].img) - iv_2.setImageURI(originList[1].img) - iv_4.setImageURI(originList[3].img) answerImg.clear() answerImg.add(originList[2].img) answerImg.add(originList[4].img) answerImg.add(originList[5].img) + cl_voice1_real.postDelayed({ + iv_1.setImageURI(originList[0].img) + iv_2.setImageURI(originList[1].img) + iv_4.setImageURI(originList[3].img) + if (cl_1.width > dip(203)){ + voiceViews.forEach { + it.layoutParams.width = dip(159) + it.layoutParams.height = dip(52) + it.requestLayout() + } + } + voiceViews.forEach { it.visible() } + },500) } voiceViews.forEachIndexed { index, constraintLayout -> if (index == 0) @@ -111,11 +121,11 @@ private fun initClick() { voiceViews.forEachIndexed { index, constraintLayout -> - constraintLayout.clickDelay { + constraintLayout.setOnClickListener { if (!playing){ if (index!=0&&!data!!.subjectList[group][index-1].listend){ myToast("请按顺序听语音") - return@clickDelay + return@setOnClickListener } voiceIndex = index handler?.sendEmptyMessage(PLAY_VOICE) diff --git a/app/src/main/java/com/dollearn/student/ui/home/ScheduleActivity.kt b/app/src/main/java/com/dollearn/student/ui/home/ScheduleActivity.kt index 512e2ea..d956c5b 100644 --- a/app/src/main/java/com/dollearn/student/ui/home/ScheduleActivity.kt +++ b/app/src/main/java/com/dollearn/student/ui/home/ScheduleActivity.kt @@ -35,31 +35,30 @@ } private fun getSchedule(){ - initTab(7) //todo test - -// HttpManager.studySchedule(week,1).request(this){_,data-> -// data?.apply { -// initTab(if (computeSchedule == 100) 7 else day) -// currentDay = day -// } -// } + HttpManager.studySchedule(week,1).request(this){_,data-> + data?.apply { + currentDay = day + initTab(if (computeSchedule == 100) 7 else day) + } + } } private fun initTab(day:Int) { - val title = titles.take(day) - title.forEachIndexed { index, s -> + titles.forEachIndexed { index, s -> if (index<5){ frags.add(DailyFragment.newInstance(index+1)) }else frags.add(WeekendFragment.newInstance(index+1)) } - val layoutParams = tab_bar.layoutParams as ConstraintLayout.LayoutParams - val anchors = listOf(R.id.tv_1,R.id.tv_2,R.id.tv_3,R.id.tv_4,R.id.tv_5,R.id.tv_6,R.id.tv_7,R.id.tv_8) - layoutParams.endToStart = anchors[day] - tab_bar.layoutParams = layoutParams - tab_bar.setViewPager(view_pager, title.toTypedArray(),this,frags) + tab_bar.setViewPager(view_pager, titles,this,frags) tab_bar.currentTab = currentDay-1 view_pager.offscreenPageLimit = day + //设置不可点击的day + (day until 6).forEach { + tab_bar.getTitleView(it).isEnabled = false + } + if (tab_bar.currentTab == 0) + tab_bar.updateTabStyles() } @Subscribe diff --git a/app/src/main/java/com/dollearn/student/ui/mine/MineFragment.kt b/app/src/main/java/com/dollearn/student/ui/mine/MineFragment.kt index 0d1bbb1..3d26d8f 100644 --- a/app/src/main/java/com/dollearn/student/ui/mine/MineFragment.kt +++ b/app/src/main/java/com/dollearn/student/ui/mine/MineFragment.kt @@ -72,7 +72,7 @@ shareDialog.callback = object :StringCallback{ override fun onResult(rst: String) { HttpManager.shareInfo().requestByF(this@MineFragment){_,data-> - ShareUtils.share(requireActivity(),if (rst == "wx") SHARE_MEDIA.WEIXIN else SHARE_MEDIA.WEIXIN_CIRCLE,data?.title?:"孩子自己就学会的英语",if (rst == "wx") "哆能智学智能教育平台" else data?.title?:"孩子自己就学会的英语", Apis.SHARE_URL, + ShareUtils.share(requireActivity(),if (rst == "wx") SHARE_MEDIA.WEIXIN else SHARE_MEDIA.WEIXIN_CIRCLE,data?.title?:"孩子自己就学会的英语",if (rst == "wx") "哆能智学教育平台" else data?.title?:"孩子自己就学会的英语", Apis.SHARE_URL, UMImage(requireContext(),data?.img?:""),object :UMShareListener{ override fun onStart(p0: SHARE_MEDIA?) { } diff --git a/app/src/main/java/com/dollearn/student/views/SlidingTabLayout.java b/app/src/main/java/com/dollearn/student/views/SlidingTabLayout.java new file mode 100644 index 0000000..81a7bf3 --- /dev/null +++ b/app/src/main/java/com/dollearn/student/views/SlidingTabLayout.java @@ -0,0 +1,923 @@ +package com.dollearn.student.views; + +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.util.AttributeSet; +import android.util.SparseArray; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.HorizontalScrollView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.flyco.tablayout.listener.OnTabSelectListener; +import com.flyco.tablayout.utils.UnreadMsgUtils; +import com.flyco.tablayout.widget.MsgView; + +import java.util.ArrayList; +import java.util.Collections; + +/** 滑动TabLayout,对于ViewPager的依赖性强 */ +public class SlidingTabLayout extends HorizontalScrollView implements ViewPager.OnPageChangeListener { + private Context mContext; + private ViewPager mViewPager; + private ArrayList<String> mTitles; + private LinearLayout mTabsContainer; + private int mCurrentTab; + private float mCurrentPositionOffset; + private int mTabCount; + /** 用于绘制显示器 */ + private Rect mIndicatorRect = new Rect(); + /** 用于实现滚动居中 */ + private Rect mTabRect = 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 int mIndicatorGravity; + private boolean mIndicatorWidthEqualTitle; + + /** 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 mTextDisableColor; + private int mTextBold; + private boolean mTextAllCaps; + + private int mLastScrollX; + private int mHeight; + private boolean mSnapOnTabClick; + + public SlidingTabLayout(Context context) { + this(context, null, 0); + } + + public SlidingTabLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setFillViewport(true);//设置滚动视图是否可以伸缩其内容以填充视口 + 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"); + + 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(); + } + } + + private void obtainAttributes(Context context, AttributeSet attrs) { + TypedArray ta = context.obtainStyledAttributes(attrs, com.flyco.tablayout.R.styleable.SlidingTabLayout); + + mIndicatorStyle = ta.getInt(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_indicator_style, STYLE_NORMAL); + mIndicatorColor = ta.getColor(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_indicator_color, Color.parseColor(mIndicatorStyle == STYLE_BLOCK ? "#4B6A87" : "#ffffff")); + mIndicatorHeight = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_indicator_height, + dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 4 : (mIndicatorStyle == STYLE_BLOCK ? -1 : 2))); + mIndicatorWidth = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_indicator_width, dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 10 : -1)); + mIndicatorCornerRadius = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_indicator_corner_radius, dp2px(mIndicatorStyle == STYLE_BLOCK ? -1 : 0)); + mIndicatorMarginLeft = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_indicator_margin_left, dp2px(0)); + mIndicatorMarginTop = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_indicator_margin_top, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0)); + mIndicatorMarginRight = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_indicator_margin_right, dp2px(0)); + mIndicatorMarginBottom = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_indicator_margin_bottom, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0)); + mIndicatorGravity = ta.getInt(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_indicator_gravity, Gravity.BOTTOM); + mIndicatorWidthEqualTitle = ta.getBoolean(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_indicator_width_equal_title, false); + + mUnderlineColor = ta.getColor(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_underline_color, Color.parseColor("#ffffff")); + mUnderlineHeight = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_underline_height, dp2px(0)); + mUnderlineGravity = ta.getInt(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_underline_gravity, Gravity.BOTTOM); + + mDividerColor = ta.getColor(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_divider_color, Color.parseColor("#ffffff")); + mDividerWidth = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_divider_width, dp2px(0)); + mDividerPadding = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_divider_padding, dp2px(12)); + + mTextsize = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_textsize, sp2px(14)); + mTextSelectColor = ta.getColor(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_textSelectColor, Color.parseColor("#ffffff")); + mTextUnselectColor = ta.getColor(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_textUnselectColor, Color.parseColor("#AAffffff")); + mTextDisableColor = Color.parseColor("#999999"); + mTextBold = ta.getInt(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_textBold, TEXT_BOLD_NONE); + mTextAllCaps = ta.getBoolean(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_textAllCaps, false); + + mTabSpaceEqual = ta.getBoolean(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_tab_space_equal, false); + mTabWidth = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_tab_width, dp2px(-1)); + mTabPadding = ta.getDimension(com.flyco.tablayout.R.styleable.SlidingTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? dp2px(0) : dp2px(20)); + + ta.recycle(); + } + + /** 关联ViewPager */ + public void setViewPager(ViewPager vp) { + if (vp == null || vp.getAdapter() == null) { + throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !"); + } + + this.mViewPager = vp; + + this.mViewPager.removeOnPageChangeListener(this); + this.mViewPager.addOnPageChangeListener(this); + notifyDataSetChanged(); + } + + /** 关联ViewPager,用于不想在ViewPager适配器中设置titles数据的情况 */ + public void setViewPager(ViewPager vp, String[] titles) { + if (vp == null || vp.getAdapter() == null) { + throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !"); + } + + if (titles == null || titles.length == 0) { + throw new IllegalStateException("Titles can not be EMPTY !"); + } + + if (titles.length != vp.getAdapter().getCount()) { + throw new IllegalStateException("Titles length must be the same as the page count !"); + } + + this.mViewPager = vp; + mTitles = new ArrayList<>(); + Collections.addAll(mTitles, titles); + + this.mViewPager.removeOnPageChangeListener(this); + this.mViewPager.addOnPageChangeListener(this); + notifyDataSetChanged(); + } + + /** 关联ViewPager,用于连适配器都不想自己实例化的情况 */ + public void setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList<Fragment> fragments) { + if (vp == null) { + throw new IllegalStateException("ViewPager can not be NULL !"); + } + + if (titles == null || titles.length == 0) { + throw new IllegalStateException("Titles can not be EMPTY !"); + } + + this.mViewPager = vp; + this.mViewPager.setAdapter(new InnerPagerAdapter(fa.getSupportFragmentManager(), fragments, titles)); + + this.mViewPager.removeOnPageChangeListener(this); + this.mViewPager.addOnPageChangeListener(this); + notifyDataSetChanged(); + } + + /** 更新数据 */ + public void notifyDataSetChanged() { + mTabsContainer.removeAllViews(); + this.mTabCount = mTitles == null ? mViewPager.getAdapter().getCount() : mTitles.size(); + View tabView; + for (int i = 0; i < mTabCount; i++) { + tabView = View.inflate(mContext, com.flyco.tablayout.R.layout.layout_tab, null); + CharSequence pageTitle = mTitles == null ? mViewPager.getAdapter().getPageTitle(i) : mTitles.get(i); + addTab(i, pageTitle.toString(), tabView); + } + + updateTabStyles(); + } + + public void addNewTab(String title) { + View tabView = View.inflate(mContext, com.flyco.tablayout.R.layout.layout_tab, null); + if (mTitles != null) { + mTitles.add(title); + } + + CharSequence pageTitle = mTitles == null ? mViewPager.getAdapter().getPageTitle(mTabCount) : mTitles.get(mTabCount); + addTab(mTabCount, pageTitle.toString(), tabView); + this.mTabCount = mTitles == null ? mViewPager.getAdapter().getCount() : mTitles.size(); + + updateTabStyles(); + } + + /** 创建并添加tab */ + private void addTab(final int position, String title, View tabView) { + TextView tv_tab_title = (TextView) tabView.findViewById(com.flyco.tablayout.R.id.tv_tab_title); + if (tv_tab_title != null) { + if (title != null) tv_tab_title.setText(title); + } + + tabView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + int position = mTabsContainer.indexOfChild(v); + if (position != -1) { + TextView tv_tab_title = (TextView) v.findViewById(com.flyco.tablayout.R.id.tv_tab_title); + if (tv_tab_title.isEnabled()) + if (mViewPager.getCurrentItem() != position) { + if (mSnapOnTabClick) { + mViewPager.setCurrentItem(position, false); + } else { + mViewPager.setCurrentItem(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); + } + + public void updateTabStyles() { + for (int i = 0; i < mTabCount; i++) { + View v = mTabsContainer.getChildAt(i); +// v.setPadding((int) mTabPadding, v.getPaddingTop(), (int) mTabPadding, v.getPaddingBottom()); + TextView tv_tab_title = (TextView) v.findViewById(com.flyco.tablayout.R.id.tv_tab_title); + if (tv_tab_title != null) { + tv_tab_title.setTextColor(i == mCurrentTab ? mTextSelectColor : (tv_tab_title.isEnabled() ? mTextUnselectColor:mTextDisableColor)); + 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); + } + } + } + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + /** + * position:当前View的位置 + * mCurrentPositionOffset:当前View的偏移量比例.[0,1) + */ + this.mCurrentTab = position; + this.mCurrentPositionOffset = positionOffset; + scrollToCurrentTab(); + invalidate(); + } + + @Override + public void onPageSelected(int position) { + updateTabSelection(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + } + + /** HorizontalScrollView滚到当前tab,并且居中显示 */ + private void scrollToCurrentTab() { + if (mTabCount <= 0) { + return; + } + + int offset = (int) (mCurrentPositionOffset * mTabsContainer.getChildAt(mCurrentTab).getWidth()); + /**当前Tab的left+当前Tab的Width乘以positionOffset*/ + int newScrollX = mTabsContainer.getChildAt(mCurrentTab).getLeft() + offset; + + if (mCurrentTab > 0 || offset > 0) { + /**HorizontalScrollView移动到当前tab,并居中*/ + newScrollX -= getWidth() / 2 - getPaddingLeft(); + calcIndicatorRect(); + newScrollX += ((mTabRect.right - mTabRect.left) / 2); + } + + if (newScrollX != mLastScrollX) { + mLastScrollX = newScrollX; + /** scrollTo(int x,int y):x,y代表的不是坐标点,而是偏移量 + * x:表示离起始位置的x水平方向的偏移量 + * y:表示离起始位置的y垂直方向的偏移量 + */ + scrollTo(newScrollX, 0); + } + } + + 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(com.flyco.tablayout.R.id.tv_tab_title); + + if (tab_title != null) { + tab_title.setTextColor(isSelect ? mTextSelectColor : (tab_title.isEnabled() ? mTextUnselectColor:mTextDisableColor)); + if (mTextBold == TEXT_BOLD_WHEN_SELECT) { + tab_title.getPaint().setFakeBoldText(isSelect); + } + } + } + } + + private float margin; + + private void calcIndicatorRect() { + View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab); + float left = currentTabView.getLeft(); + float right = currentTabView.getRight(); + + //for mIndicatorWidthEqualTitle + if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) { + TextView tab_title = (TextView) currentTabView.findViewById(com.flyco.tablayout.R.id.tv_tab_title); + mTextPaint.setTextSize(mTextsize); + float textWidth = mTextPaint.measureText(tab_title.getText().toString()); + margin = (right - left - textWidth) / 2; + } + + if (this.mCurrentTab < mTabCount - 1) { + View nextTabView = mTabsContainer.getChildAt(this.mCurrentTab + 1); + float nextTabLeft = nextTabView.getLeft(); + float nextTabRight = nextTabView.getRight(); + + left = left + mCurrentPositionOffset * (nextTabLeft - left); + right = right + mCurrentPositionOffset * (nextTabRight - right); + + //for mIndicatorWidthEqualTitle + if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) { + TextView next_tab_title = (TextView) nextTabView.findViewById(com.flyco.tablayout.R.id.tv_tab_title); + mTextPaint.setTextSize(mTextsize); + float nextTextWidth = mTextPaint.measureText(next_tab_title.getText().toString()); + float nextMargin = (nextTabRight - nextTabLeft - nextTextWidth) / 2; + margin = margin + mCurrentPositionOffset * (nextMargin - margin); + } + } + + mIndicatorRect.left = (int) left; + mIndicatorRect.right = (int) right; + //for mIndicatorWidthEqualTitle + if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) { + mIndicatorRect.left = (int) (left + margin - 1); + mIndicatorRect.right = (int) (right - margin - 1); + } + + mTabRect.left = (int) left; + mTabRect.right = (int) right; + + if (mIndicatorWidth < 0) { //indicatorWidth小于0时,原jpardogo's PagerSlidingTabStrip + + } else {//indicatorWidth大于0时,圆角矩形以及三角形 + float indicatorLeft = currentTabView.getLeft() + (currentTabView.getWidth() - mIndicatorWidth) / 2; + + if (this.mCurrentTab < mTabCount - 1) { + View nextTab = mTabsContainer.getChildAt(this.mCurrentTab + 1); + indicatorLeft = indicatorLeft + mCurrentPositionOffset * (currentTabView.getWidth() / 2 + nextTab.getWidth() / 2); + } + + mIndicatorRect.left = (int) indicatorLeft; + mIndicatorRect.right = (int) (mIndicatorRect.left + mIndicatorWidth); + } + } + + @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 + + 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) { + this.mCurrentTab = currentTab; + mViewPager.setCurrentItem(currentTab); + + } + + public void setCurrentTab(int currentTab, boolean smoothScroll) { + this.mCurrentTab = currentTab; + mViewPager.setCurrentItem(currentTab, smoothScroll); + } + + 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 setIndicatorWidthEqualTitle(boolean indicatorWidthEqualTitle) { + this.mIndicatorWidthEqualTitle = indicatorWidthEqualTitle; + invalidate(); + } + + 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 setTextAllCaps(boolean textAllCaps) { + this.mTextAllCaps = textAllCaps; + updateTabStyles(); + } + + public void setSnapOnTabClick(boolean snapOnTabClick) { + mSnapOnTabClick = snapOnTabClick; + } + + + 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 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 TextView getTitleView(int tab) { + View tabView = mTabsContainer.getChildAt(tab); + TextView tv_tab_title = (TextView) tabView.findViewById(com.flyco.tablayout.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(com.flyco.tablayout.R.id.rtv_msg_tip); + if (tipView != null) { + UnreadMsgUtils.show(tipView, num); + + if (mInitSetMap.get(position) != null && mInitSetMap.get(position)) { + return; + } + + setMsgMargin(position, 4, 2); + 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(com.flyco.tablayout.R.id.rtv_msg_tip); + if (tipView != null) { + tipView.setVisibility(View.GONE); + } + } + + /** 设置未读消息偏移,原点为文字的右上角.当控件高度固定,消息提示位置易控制,显示效果佳 */ + 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(com.flyco.tablayout.R.id.rtv_msg_tip); + if (tipView != null) { + TextView tv_tab_title = (TextView) tabView.findViewById(com.flyco.tablayout.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(); + lp.leftMargin = mTabWidth >= 0 ? (int) (mTabWidth / 2 + textWidth / 2 + dp2px(leftPadding)) : (int) (mTabPadding + textWidth + dp2px(leftPadding)); + lp.topMargin = mHeight > 0 ? (int) (mHeight - textHeight) / 2 - dp2px(bottomPadding) : 0; + 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(com.flyco.tablayout.R.id.rtv_msg_tip); + return tipView; + } + + private OnTabSelectListener mListener; + + public void setOnTabSelectListener(OnTabSelectListener listener) { + this.mListener = listener; + } + + class InnerPagerAdapter extends FragmentPagerAdapter { + private ArrayList<Fragment> fragments = new ArrayList<>(); + private String[] titles; + + public InnerPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragments, String[] titles) { + super(fm); + this.fragments = fragments; + this.titles = titles; + } + + @Override + public int getCount() { + return fragments.size(); + } + + @Override + public CharSequence getPageTitle(int position) { + return titles[position]; + } + + @Override + public Fragment getItem(int position) { + return fragments.get(position); + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + // 覆写destroyItem并且空实现,这样每个Fragment中的视图就不会被销毁 + // super.destroyItem(container, position, object); + } + + @Override + public int getItemPosition(Object object) { + return PagerAdapter.POSITION_NONE; + } + } + + @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); + scrollToCurrentTab(); + } + } + super.onRestoreInstanceState(state); + } + + 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); + } +} diff --git a/app/src/main/res/layout/activity_schedul.xml b/app/src/main/res/layout/activity_schedul.xml index fa1c219..9fadd33 100644 --- a/app/src/main/res/layout/activity_schedul.xml +++ b/app/src/main/res/layout/activity_schedul.xml @@ -108,8 +108,8 @@ android:layout_height="match_parent" android:id="@+id/tv_8" app:layout_constraintEnd_toEndOf="parent"/> - <com.flyco.tablayout.SlidingTabLayout - android:layout_width="0dp" + <com.dollearn.student.views.SlidingTabLayout + android:layout_width="match_parent" android:layout_height="50dp" android:id="@+id/tab_bar" app:layout_constraintTop_toTopOf="parent" diff --git a/app/src/main/res/layout/fragment_include.xml b/app/src/main/res/layout/fragment_include.xml index c8a2a56..db1f053 100644 --- a/app/src/main/res/layout/fragment_include.xml +++ b/app/src/main/res/layout/fragment_include.xml @@ -150,40 +150,49 @@ app:layout_constraintDimensionRatio="3:1" app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="15dp" - android:id="@+id/cl_voice1" android:layout_marginStart="4dp" - android:layout_marginEnd="40dp" - android:background="@drawable/selector_bg_voice"> - <ImageView - android:id="@+id/iv1_1" - android:layout_width="wrap_content" + android:id="@+id/cl_voice1" + android:layout_marginEnd="40dp"> + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:id="@+id/cl_voice1_real" + android:visibility="gone" android:layout_height="match_parent" - android:layout_marginVertical="6dp" - android:src="@mipmap/yuyin" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" - android:layout_marginStart="25dp"/> - <ImageView - android:id="@+id/iv2_1" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginVertical="6dp" - android:src="@mipmap/play" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - android:layout_marginEnd="23dp"/> - <ImageView - android:id="@+id/iv_playing_1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:visibility="gone" - android:src="@mipmap/bofangzhong" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" /> + android:background="@drawable/selector_bg_voice"> + <ImageView + android:id="@+id/iv1_1" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginVertical="6dp" + android:src="@mipmap/yuyin" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + android:layout_marginStart="25dp"/> + <ImageView + android:id="@+id/iv2_1" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginVertical="6dp" + android:src="@mipmap/play" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + android:layout_marginEnd="23dp"/> + <ImageView + android:id="@+id/iv_playing_1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:src="@mipmap/bofangzhong" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> + </androidx.constraintlayout.widget.ConstraintLayout> + </androidx.constraintlayout.widget.ConstraintLayout> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="0dp" @@ -194,7 +203,14 @@ app:layout_constraintTop_toTopOf="@id/cl_voice1" android:id="@+id/cl_voice2" android:layout_marginStart="4dp" - android:layout_marginEnd="40dp" + android:layout_marginEnd="40dp"> + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:id="@+id/cl_voice2_real" + android:visibility="gone" + android:layout_height="match_parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" android:background="@drawable/selector_bg_voice"> <ImageView android:id="@+id/iv1_2" @@ -227,6 +243,8 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> + + </androidx.constraintlayout.widget.ConstraintLayout> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="0dp" android:layout_height="0dp" @@ -236,38 +254,48 @@ app:layout_constraintTop_toTopOf="@id/cl_voice1" android:id="@+id/cl_voice3" android:layout_marginStart="4dp" - android:layout_marginEnd="40dp" - android:background="@drawable/selector_bg_voice"> - <ImageView - android:id="@+id/iv1_3" - android:layout_width="wrap_content" + android:layout_marginEnd="40dp"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:id="@+id/cl_voice3_real" + android:visibility="gone" android:layout_height="match_parent" - android:layout_marginVertical="6dp" - android:src="@mipmap/yuyin" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" - android:layout_marginStart="25dp"/> - <ImageView - android:id="@+id/iv2_3" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginVertical="6dp" - android:src="@mipmap/play" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - android:layout_marginEnd="23dp"/> - <ImageView - android:id="@+id/iv_playing_3" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:visibility="gone" - android:src="@mipmap/bofangzhong" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" /> + android:background="@drawable/selector_bg_voice"> + <ImageView + android:id="@+id/iv1_3" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginVertical="6dp" + android:src="@mipmap/yuyin" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + android:layout_marginStart="25dp"/> + <ImageView + android:id="@+id/iv2_3" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginVertical="6dp" + android:src="@mipmap/play" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + android:layout_marginEnd="23dp"/> + <ImageView + android:id="@+id/iv_playing_3" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:src="@mipmap/bofangzhong" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> + </androidx.constraintlayout.widget.ConstraintLayout> + </androidx.constraintlayout.widget.ConstraintLayout> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="0dp" @@ -279,38 +307,48 @@ android:layout_marginBottom="14dp" android:id="@+id/cl_voice4" android:layout_marginStart="4dp" - android:layout_marginEnd="40dp" - android:background="@drawable/selector_bg_voice"> - <ImageView - android:id="@+id/iv1_4" - android:layout_width="wrap_content" + android:layout_marginEnd="40dp"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:id="@+id/cl_voice4_real" + android:visibility="gone" android:layout_height="match_parent" - android:layout_marginVertical="6dp" - android:src="@mipmap/yuyin" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" - android:layout_marginStart="25dp"/> - <ImageView - android:id="@+id/iv2_4" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginVertical="6dp" - android:src="@mipmap/play" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - android:layout_marginEnd="23dp"/> - <ImageView - android:id="@+id/iv_playing_4" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:visibility="gone" - android:src="@mipmap/bofangzhong" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" /> + android:background="@drawable/selector_bg_voice"> + <ImageView + android:id="@+id/iv1_4" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginVertical="6dp" + android:src="@mipmap/yuyin" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + android:layout_marginStart="25dp"/> + <ImageView + android:id="@+id/iv2_4" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginVertical="6dp" + android:src="@mipmap/play" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + android:layout_marginEnd="23dp"/> + <ImageView + android:id="@+id/iv_playing_4" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:src="@mipmap/bofangzhong" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> + </androidx.constraintlayout.widget.ConstraintLayout> + </androidx.constraintlayout.widget.ConstraintLayout> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="0dp" @@ -321,38 +359,48 @@ android:layout_marginEnd="40dp" app:layout_constraintTop_toTopOf="@id/cl_voice4" android:id="@+id/cl_voice5" - android:layout_marginStart="4dp" - android:background="@drawable/selector_bg_voice"> - <ImageView - android:id="@+id/iv1_5" - android:layout_width="wrap_content" + android:layout_marginStart="4dp"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:id="@+id/cl_voice5_real" + android:visibility="gone" android:layout_height="match_parent" - android:layout_marginVertical="6dp" - android:src="@mipmap/yuyin" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" - android:layout_marginStart="25dp"/> - <ImageView - android:id="@+id/iv2_5" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginVertical="6dp" - android:src="@mipmap/play" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - android:layout_marginEnd="23dp"/> - <ImageView - android:id="@+id/iv_playing_5" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:visibility="gone" - android:src="@mipmap/bofangzhong" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" /> + android:background="@drawable/selector_bg_voice"> + <ImageView + android:id="@+id/iv1_5" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginVertical="6dp" + android:src="@mipmap/yuyin" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + android:layout_marginStart="25dp"/> + <ImageView + android:id="@+id/iv2_5" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginVertical="6dp" + android:src="@mipmap/play" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + android:layout_marginEnd="23dp"/> + <ImageView + android:id="@+id/iv_playing_5" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:src="@mipmap/bofangzhong" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> + </androidx.constraintlayout.widget.ConstraintLayout> + </androidx.constraintlayout.widget.ConstraintLayout> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="0dp" @@ -363,38 +411,48 @@ android:layout_marginEnd="40dp" app:layout_constraintTop_toTopOf="@id/cl_voice4" android:id="@+id/cl_voice6" - android:layout_marginStart="4dp" - android:background="@drawable/selector_bg_voice"> - <ImageView - android:id="@+id/iv1_6" - android:layout_width="wrap_content" + android:layout_marginStart="4dp"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:id="@+id/cl_voice6_real" + android:visibility="gone" android:layout_height="match_parent" - android:layout_marginVertical="6dp" - android:src="@mipmap/yuyin" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" - android:layout_marginStart="25dp"/> - <ImageView - android:id="@+id/iv2_6" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginVertical="6dp" - android:src="@mipmap/play" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - android:layout_marginEnd="23dp"/> - <ImageView - android:id="@+id/iv_playing_6" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:visibility="gone" - android:src="@mipmap/bofangzhong" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" /> + android:background="@drawable/selector_bg_voice"> + <ImageView + android:id="@+id/iv1_6" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginVertical="6dp" + android:src="@mipmap/yuyin" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + android:layout_marginStart="25dp"/> + <ImageView + android:id="@+id/iv2_6" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginVertical="6dp" + android:src="@mipmap/play" + app:layout_constraintTop_toTopOf="parent" + android:layout_marginEnd="23dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" /> + <ImageView + android:id="@+id/iv_playing_6" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:src="@mipmap/bofangzhong" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> + </androidx.constraintlayout.widget.ConstraintLayout> + </androidx.constraintlayout.widget.ConstraintLayout> <com.facebook.drawee.view.SimpleDraweeView -- Gitblit v1.7.1