From: @sishuikang Reviewed-by: @zhanghaibo5,@zhanghaibo5,@hangangqiang Signed-off-by: @zhanghaibo5pull/14624/MERGE
| @@ -15,9 +15,10 @@ | |||
| */ | |||
| package com.mindspore.himindspore.bean; | |||
| import com.mindspore.customview.tablayout.listener.CustomTabEntity; | |||
| public class TabEntity implements CustomTabEntity { | |||
| import com.mindspore.himindspore.ui.view.MSTabEntity; | |||
| public class TabEntity implements MSTabEntity { | |||
| public String title; | |||
| public int selectedIcon; | |||
| @@ -30,17 +31,17 @@ public class TabEntity implements CustomTabEntity { | |||
| } | |||
| @Override | |||
| public String getTabTitle() { | |||
| public String getMSTabTitle() { | |||
| return title; | |||
| } | |||
| @Override | |||
| public int getTabSelectedIcon() { | |||
| public int getMSTabIconChecked() { | |||
| return selectedIcon; | |||
| } | |||
| @Override | |||
| public int getTabUnselectedIcon() { | |||
| public int getMSTabIconUnchecked() { | |||
| return unSelectedIcon; | |||
| } | |||
| } | |||
| @@ -40,7 +40,7 @@ import androidx.appcompat.app.AlertDialog; | |||
| import com.mindspore.common.sp.Preferences; | |||
| import com.mindspore.common.utils.Utils; | |||
| import com.mindspore.customview.countdown.CountDownView; | |||
| import com.mindspore.customview.countdown.MSCountDownView; | |||
| import com.mindspore.himindspore.R; | |||
| import com.mindspore.himindspore.base.BaseActivity; | |||
| import com.mindspore.himindspore.ui.main.MainActivity; | |||
| @@ -63,7 +63,7 @@ public class SplashActivity extends BaseActivity implements EasyPermissions.Perm | |||
| private SharedPreferences prefs; | |||
| private CountDownView cdvTime; | |||
| private MSCountDownView cdvTime; | |||
| private boolean isCheckPrivacy = false; | |||
| private View mContentView; | |||
| @@ -24,22 +24,25 @@ import android.net.Uri; | |||
| import android.os.Build; | |||
| import android.os.Environment; | |||
| import android.util.Log; | |||
| import android.view.LayoutInflater; | |||
| import android.view.View; | |||
| import android.widget.ImageView; | |||
| import android.widget.TextView; | |||
| import android.widget.Toast; | |||
| import androidx.core.content.FileProvider; | |||
| import androidx.fragment.app.Fragment; | |||
| import androidx.viewpager.widget.ViewPager; | |||
| import com.google.android.material.tabs.TabLayout; | |||
| import com.mindspore.common.base.adapter.BasePagerAdapter; | |||
| import com.mindspore.customview.dialog.UpdateDialog; | |||
| import com.mindspore.customview.tablayout.CommonTabLayout; | |||
| import com.mindspore.customview.tablayout.listener.CustomTabEntity; | |||
| import com.mindspore.customview.tablayout.listener.OnTabSelectListener; | |||
| import com.mindspore.himindspore.R; | |||
| import com.mindspore.himindspore.base.BaseActivity; | |||
| import com.mindspore.himindspore.comment.FragmentFactory; | |||
| import com.mindspore.himindspore.net.FileDownLoadObserver; | |||
| import com.mindspore.himindspore.net.UpdateInfoBean; | |||
| import com.mindspore.himindspore.ui.view.MSTabEntity; | |||
| import java.io.File; | |||
| import java.util.ArrayList; | |||
| @@ -49,16 +52,18 @@ public class MainActivity extends BaseActivity<MainPresenter> implements MainCon | |||
| private static final String TAG = "MainActivity"; | |||
| private ViewPager mVpHome; | |||
| private CommonTabLayout mCtlTable; | |||
| private TabLayout mTabLayout; | |||
| private int now_version; | |||
| private ProgressDialog progressDialog; | |||
| private List<MSTabEntity> mTabEntities; | |||
| @Override | |||
| protected void init() { | |||
| presenter = new MainPresenter(this); | |||
| mVpHome = findViewById(R.id.vp_home); | |||
| mCtlTable = findViewById(R.id.ctl_table); | |||
| mTabLayout = findViewById(R.id.tab_layout); | |||
| showPackaeInfo(); | |||
| initTabLayout(); | |||
| initViewPager(); | |||
| @@ -82,19 +87,68 @@ public class MainActivity extends BaseActivity<MainPresenter> implements MainCon | |||
| } | |||
| private void initTabLayout() { | |||
| ArrayList<CustomTabEntity> mTabEntities = presenter.getTabEntity(); | |||
| mCtlTable.setTabData(mTabEntities); | |||
| mCtlTable.setOnTabSelectListener(new OnTabSelectListener() { | |||
| mTabEntities = presenter.getTabEntity(); | |||
| for (int i = 0; i < mTabEntities.size(); i++) { | |||
| mTabLayout.addTab(mTabLayout.newTab().setCustomView(getTabView(mTabEntities.get(i)))); | |||
| } | |||
| chooseFirst(); | |||
| mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { | |||
| @Override | |||
| public void onTabSelect(int position) { | |||
| mVpHome.setCurrentItem(position); | |||
| public void onTabSelected(TabLayout.Tab tab) { | |||
| Log.e(TAG, "onTabSelected: " + tab.getPosition()); | |||
| mVpHome.setCurrentItem(tab.getPosition(),true); | |||
| recoverItem(); | |||
| View view =tab.getCustomView(); | |||
| ImageView imageView = view.findViewById(R.id.tab_icon); | |||
| TextView textView = view.findViewById(R.id.tab_title); | |||
| imageView.setImageResource(mTabEntities.get(tab.getPosition()).getMSTabIconChecked()); | |||
| textView.setTextColor(getResources().getColor(R.color.main_tab_text_checked)); | |||
| } | |||
| @Override | |||
| public void onTabUnselected(TabLayout.Tab tab) { | |||
| } | |||
| @Override | |||
| public void onTabReselect(int position) { | |||
| public void onTabReselected(TabLayout.Tab tab) { | |||
| } | |||
| }); | |||
| } | |||
| public View getTabView(MSTabEntity tabEntity) { | |||
| View view = LayoutInflater.from(this).inflate(R.layout.layout_tab_top, null); | |||
| ImageView tabIcon = view.findViewById(R.id.tab_icon); | |||
| tabIcon.setImageResource(tabEntity.getMSTabIconUnchecked()); | |||
| TextView tabText = view.findViewById(R.id.tab_title); | |||
| tabText.setText(tabEntity.getMSTabTitle()); | |||
| tabText.setTextColor(getResources().getColor(R.color.main_tab_text_uncheck)); | |||
| return view; | |||
| } | |||
| private void chooseFirst() { | |||
| TabLayout.Tab tabAt = mTabLayout.getTabAt(0); | |||
| View view = tabAt.getCustomView(); | |||
| ImageView imageView = view.findViewById(R.id.tab_icon); | |||
| TextView textView = view.findViewById(R.id.tab_title); | |||
| imageView.setImageResource(mTabEntities.get(0).getMSTabIconChecked()); | |||
| textView.setTextColor(getResources().getColor(R.color.main_tab_text_checked)); | |||
| } | |||
| private void recoverItem() { | |||
| for (int i = 0; i < mTabEntities.size(); i++) { | |||
| TabLayout.Tab tabAt = mTabLayout.getTabAt(i); | |||
| View view = tabAt.getCustomView(); | |||
| ImageView imageView = view.findViewById(R.id.tab_icon); | |||
| TextView textView = view.findViewById(R.id.tab_title); | |||
| imageView.setImageResource(mTabEntities.get(i).getMSTabIconUnchecked()); | |||
| textView.setTextColor(getResources().getColor(R.color.main_tab_text_uncheck)); | |||
| } | |||
| } | |||
| private void initViewPager() { | |||
| @@ -104,23 +158,7 @@ public class MainActivity extends BaseActivity<MainPresenter> implements MainCon | |||
| fragments.add(FragmentFactory.getInstance().getMeFragment()); | |||
| BasePagerAdapter adapter = new BasePagerAdapter(getSupportFragmentManager(), fragments); | |||
| mVpHome.setAdapter(adapter); | |||
| mVpHome.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { | |||
| @Override | |||
| public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { | |||
| } | |||
| @Override | |||
| public void onPageSelected(int position) { | |||
| if (position >= 0) { | |||
| mCtlTable.setCurrentTab(position); | |||
| } | |||
| } | |||
| @Override | |||
| public void onPageScrollStateChanged(int state) { | |||
| } | |||
| }); | |||
| mVpHome.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout)); | |||
| mVpHome.setOffscreenPageLimit(3); | |||
| mVpHome.setCurrentItem(0); | |||
| } | |||
| @@ -171,7 +209,7 @@ public class MainActivity extends BaseActivity<MainPresenter> implements MainCon | |||
| public void showUpdate(final UpdateInfoBean updateInfo) { | |||
| if (now_version != updateInfo.getVersionCode()) { | |||
| UpdateDialog updateDialog= new UpdateDialog(this); | |||
| UpdateDialog updateDialog = new UpdateDialog(this); | |||
| updateDialog.setTitleString(getResources().getString(R.string.app_update_lastest) + updateInfo.getVersionName()); | |||
| updateDialog.setContentString(updateInfo.getMessage()); | |||
| updateDialog.setYesOnclickListener(() -> downFile()); | |||
| @@ -201,12 +239,9 @@ public class MainActivity extends BaseActivity<MainPresenter> implements MainCon | |||
| @Override | |||
| public void onProgress(final int progress, final long total) { | |||
| runOnUiThread(new Runnable() { | |||
| @Override | |||
| public void run() { | |||
| progressDialog.setMax((int) total / 1024 / 1024); | |||
| progressDialog.setProgress(progress); | |||
| } | |||
| runOnUiThread(() -> { | |||
| progressDialog.setMax((int) total / 1024 / 1024); | |||
| progressDialog.setProgress(progress); | |||
| }); | |||
| } | |||
| @@ -15,12 +15,12 @@ | |||
| */ | |||
| package com.mindspore.himindspore.ui.main; | |||
| import com.mindspore.customview.tablayout.listener.CustomTabEntity; | |||
| import com.mindspore.himindspore.net.FileDownLoadObserver; | |||
| import com.mindspore.himindspore.net.UpdateInfoBean; | |||
| import com.mindspore.himindspore.ui.view.MSTabEntity; | |||
| import java.io.File; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| public interface MainContract { | |||
| @@ -31,7 +31,7 @@ public interface MainContract { | |||
| } | |||
| interface Presenter { | |||
| ArrayList<CustomTabEntity> getTabEntity(); | |||
| List<MSTabEntity> getTabEntity(); | |||
| void getUpdateInfo(); | |||
| @@ -19,13 +19,13 @@ import android.content.res.TypedArray; | |||
| import android.util.Log; | |||
| import com.mindspore.common.utils.Utils; | |||
| import com.mindspore.customview.tablayout.listener.CustomTabEntity; | |||
| import com.mindspore.himindspore.R; | |||
| import com.mindspore.himindspore.base.BasePresenter; | |||
| import com.mindspore.himindspore.bean.TabEntity; | |||
| import com.mindspore.himindspore.net.FileDownLoadObserver; | |||
| import com.mindspore.himindspore.net.RetrofitHelper; | |||
| import com.mindspore.himindspore.net.UpdateInfoBean; | |||
| import com.mindspore.himindspore.ui.view.MSTabEntity; | |||
| import java.io.File; | |||
| import java.util.ArrayList; | |||
| @@ -51,15 +51,15 @@ public class MainPresenter extends BasePresenter<MainActivity> implements MainCo | |||
| @Override | |||
| public ArrayList<CustomTabEntity> getTabEntity() { | |||
| ArrayList<CustomTabEntity> mTabEntities = new ArrayList<>(); | |||
| public ArrayList<MSTabEntity> getTabEntity() { | |||
| ArrayList<MSTabEntity> mTabEntities = new ArrayList<>(); | |||
| TypedArray mIconUnSelectIds = Utils.getApp().getResources().obtainTypedArray(R.array.main_tab_un_select); | |||
| TypedArray mIconSelectIds = Utils.getApp().getResources().obtainTypedArray(R.array.main_tab_select); | |||
| String[] mainTitles = Utils.getApp().getResources().getStringArray(R.array.main_tab_title); | |||
| for (int i = 0; i < mainTitles.length; i++) { | |||
| int unSelectId = mIconUnSelectIds.getResourceId(i, R.drawable.experience_uncheck); | |||
| int selectId = mIconSelectIds.getResourceId(i, R.drawable.experience_checked); | |||
| mTabEntities.add(new TabEntity(mainTitles[i],selectId , unSelectId)); | |||
| mTabEntities.add(new TabEntity(mainTitles[i], selectId, unSelectId)); | |||
| } | |||
| mIconUnSelectIds.recycle(); | |||
| mIconSelectIds.recycle(); | |||
| @@ -13,16 +13,16 @@ | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package com.mindspore.customview.tablayout.listener; | |||
| package com.mindspore.himindspore.ui.view; | |||
| import androidx.annotation.DrawableRes; | |||
| public interface CustomTabEntity { | |||
| String getTabTitle(); | |||
| public interface MSTabEntity { | |||
| String getMSTabTitle(); | |||
| @DrawableRes | |||
| int getTabSelectedIcon(); | |||
| int getMSTabIconChecked(); | |||
| @DrawableRes | |||
| int getTabUnselectedIcon(); | |||
| int getMSTabIconUnchecked(); | |||
| } | |||
| @@ -1,43 +1,36 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
| xmlns:app="http://schemas.android.com/apk/res-auto" | |||
| android:layout_width="match_parent" | |||
| android:layout_height="match_parent" | |||
| android:orientation="vertical"> | |||
| <com.mindspore.customview.tablayout.CommonTabLayout | |||
| android:layout_alignParentBottom="true" | |||
| android:id="@+id/ctl_table" | |||
| <androidx.viewpager.widget.ViewPager | |||
| android:id="@+id/vp_home" | |||
| android:layout_width="match_parent" | |||
| android:layout_height="50dp" | |||
| android:background="@color/white" | |||
| app:tl_iconHeight="23dp" | |||
| app:tl_iconWidth="23dp" | |||
| app:tl_indicator_color="#2C97DE" | |||
| app:tl_indicator_height="0dp" | |||
| app:tl_textSelectColor="@color/main_tab_text_checked" | |||
| app:tl_textUnselectColor="@color/main_tab_text_uncheck" | |||
| app:tl_textsize="12sp" | |||
| app:tl_underline_color="#DDDDDD" | |||
| app:tl_underline_height="1dp" /> | |||
| android:layout_height="0dp" | |||
| android:layout_weight="1" | |||
| android:background="@color/white" /> | |||
| <View | |||
| android:id="@+id/lineView" | |||
| android:layout_above="@+id/ctl_table" | |||
| android:layout_width="match_parent" | |||
| android:layout_height="1px" | |||
| android:layout_height="1dp" | |||
| android:background="@color/divider_gray" /> | |||
| <androidx.viewpager.widget.ViewPager | |||
| android:layout_above="@+id/lineView" | |||
| android:id="@+id/vp_home" | |||
| <com.google.android.material.tabs.TabLayout | |||
| android:id="@+id/tab_layout" | |||
| android:layout_width="match_parent" | |||
| android:layout_height="match_parent" | |||
| android:background="@color/white" /> | |||
| </RelativeLayout> | |||
| android:layout_height="55dp" | |||
| android:background="@color/white" | |||
| app:tabGravity="fill" | |||
| app:tabIndicatorFullWidth="false" | |||
| app:tabIndicatorGravity="center" | |||
| app:tabIndicatorHeight="0dp" | |||
| app:tabMaxWidth="0dp" | |||
| app:tabMode="fixed" | |||
| app:tabRippleColor="@android:color/transparent" | |||
| app:tabSelectedTextColor="@color/main_tab_text_checked" | |||
| app:tabTextColor="@color/main_tab_text_uncheck" /> | |||
| </LinearLayout> | |||
| @@ -7,7 +7,6 @@ | |||
| android:background="@color/white" | |||
| tools:context=".ui.guide.SplashActivity"> | |||
| <ImageView | |||
| android:id="@+id/image_logo" | |||
| android:layout_width="160dp" | |||
| @@ -48,23 +47,23 @@ | |||
| app:layout_constraintTop_toBottomOf="@+id/title" /> | |||
| <com.mindspore.customview.countdown.CountDownView | |||
| <com.mindspore.customview.countdown.MSCountDownView | |||
| android:id="@+id/cdv_time" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:layout_gravity="end" | |||
| android:layout_marginTop="40dp" | |||
| android:layout_marginEnd="20dp" | |||
| app:cd_animator_time="3" | |||
| app:cd_animator_time_unit="@string/splash_count_down" | |||
| app:cd_arc_color="@color/btn_small_checked" | |||
| app:cd_arc_width="2dp" | |||
| app:cd_bg_color="@color/gray_light" | |||
| app:cd_circle_radius="20dp" | |||
| app:cd_location="top" | |||
| app:cd_retreat_type="forward" | |||
| app:cd_text_color="@color/black" | |||
| app:cd_text_size="12sp" | |||
| app:layout_constraintEnd_toEndOf="parent" | |||
| app:layout_constraintTop_toTopOf="parent" /> | |||
| app:layout_constraintTop_toTopOf="parent" | |||
| app:ms_cd_animator_time="3" | |||
| app:ms_cd_animator_time_unit="@string/splash_count_down" | |||
| app:ms_cd_arc_color="@color/btn_small_checked" | |||
| app:ms_cd_arc_width="2dp" | |||
| app:ms_cd_bg_color="@color/gray_light" | |||
| app:ms_cd_circle_radius="20dp" | |||
| app:ms_cd_location="top" | |||
| app:ms_cd_retreat_type="forward" | |||
| app:ms_cd_text_color="@color/black" | |||
| app:ms_cd_text_size="12sp" /> | |||
| </androidx.constraintlayout.widget.ConstraintLayout> | |||
| @@ -0,0 +1,31 @@ | |||
| <?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:clipChildren="false" | |||
| android:clipToPadding="false"> | |||
| <LinearLayout | |||
| android:id="@+id/ll_tap" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:layout_centerInParent="true" | |||
| android:gravity="center" | |||
| android:orientation="vertical"> | |||
| <ImageView | |||
| android:id="@+id/tab_icon" | |||
| android:layout_width="23dp" | |||
| android:layout_height="23dp"/> | |||
| <TextView | |||
| android:textSize="12sp" | |||
| android:id="@+id/tab_title" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:singleLine="true"/> | |||
| </LinearLayout> | |||
| </RelativeLayout> | |||
| @@ -1,253 +0,0 @@ | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * <p> | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * <p> | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * <p> | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package com.mindspore.customview.countdown; | |||
| import android.animation.Animator; | |||
| import android.animation.AnimatorListenerAdapter; | |||
| import android.animation.AnimatorSet; | |||
| import android.animation.ValueAnimator; | |||
| import android.annotation.TargetApi; | |||
| import android.content.Context; | |||
| import android.content.res.TypedArray; | |||
| import android.graphics.Canvas; | |||
| import android.graphics.Color; | |||
| import android.graphics.Paint; | |||
| import android.graphics.RectF; | |||
| import android.graphics.Typeface; | |||
| import android.os.Build; | |||
| import android.text.TextUtils; | |||
| import android.util.AttributeSet; | |||
| import android.view.View; | |||
| import android.view.animation.LinearInterpolator; | |||
| import androidx.annotation.Nullable; | |||
| import androidx.core.content.ContextCompat; | |||
| import com.mindspore.customview.R; | |||
| public class CountDownView extends View { | |||
| private Context mContext;//上下文 | |||
| private Paint mPaintBackGround;//背景画笔 | |||
| private Paint mPaintArc;//圆弧画笔 | |||
| private Paint mPaintText;//文字画笔 | |||
| private int mRetreatType;//圆弧绘制方式(增加和减少) | |||
| private float mPaintArcWidth;//最外层圆弧的宽度 | |||
| private int mCircleRadius;//圆圈的半径 | |||
| private int mPaintArcColor = Color.parseColor("#3C3F41");//初始值 | |||
| private int mPaintBackGroundColor = Color.parseColor("#55B2E5");//初始值 | |||
| private int mLoadingTime;//时间,单位秒 | |||
| private String mLoadingTimeUnit = "";//时间单位 | |||
| private int mTextColor = Color.BLACK;//字体颜色 | |||
| private int mTextSize;//字体大小 | |||
| private int location;//从哪个位置开始 | |||
| private float startAngle;//开始角度 | |||
| private float mmSweepAngleStart;//起点 | |||
| private float mmSweepAngleEnd;//终点 | |||
| private float mSweepAngle;//扫过的角度 | |||
| private String mText = "";//要绘制的文字 | |||
| private int mWidth; | |||
| private int mHeight; | |||
| private AnimatorSet set; | |||
| public CountDownView(Context context) { | |||
| this(context, null); | |||
| } | |||
| public CountDownView(Context context, @Nullable AttributeSet attrs) { | |||
| this(context, attrs, 0); | |||
| } | |||
| public CountDownView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { | |||
| super(context, attrs, defStyleAttr); | |||
| mContext = context; | |||
| TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CountDownView); | |||
| mRetreatType = array.getInt(R.styleable.CountDownView_cd_retreat_type, 1); | |||
| location = array.getInt(R.styleable.CountDownView_cd_location, 1); | |||
| mCircleRadius = (int) array.getDimension(R.styleable.CountDownView_cd_circle_radius, dip2px(context, 25));//默认25dp | |||
| mPaintArcWidth = array.getDimension(R.styleable.CountDownView_cd_arc_width, dip2px(context, 3));//默认3dp | |||
| mPaintArcColor = array.getColor(R.styleable.CountDownView_cd_arc_color, mPaintArcColor); | |||
| mTextSize = (int) array.getDimension(R.styleable.CountDownView_cd_text_size, dip2px(context, 14));//默认14sp | |||
| mTextColor = array.getColor(R.styleable.CountDownView_cd_text_color, mTextColor); | |||
| mPaintBackGroundColor = array.getColor(R.styleable.CountDownView_cd_bg_color, mPaintBackGroundColor); | |||
| mLoadingTime = array.getInteger(R.styleable.CountDownView_cd_animator_time, 3);//默认3秒 | |||
| mLoadingTimeUnit = array.getString(R.styleable.CountDownView_cd_animator_time_unit);//时间单位 | |||
| if (TextUtils.isEmpty(mLoadingTimeUnit)) { | |||
| mLoadingTimeUnit = ""; | |||
| } | |||
| array.recycle(); | |||
| init(); | |||
| } | |||
| @TargetApi(Build.VERSION_CODES.JELLY_BEAN) | |||
| private void init() { | |||
| //背景设为透明,然后造成圆形View的视觉错觉 | |||
| this.setBackground(ContextCompat.getDrawable(mContext, android.R.color.transparent)); | |||
| mPaintBackGround = new Paint(); | |||
| mPaintBackGround.setStyle(Paint.Style.FILL); | |||
| mPaintBackGround.setAntiAlias(true); | |||
| mPaintBackGround.setColor(mPaintBackGroundColor); | |||
| mPaintArc = new Paint(); | |||
| mPaintArc.setStyle(Paint.Style.STROKE); | |||
| mPaintArc.setAntiAlias(true); | |||
| mPaintArc.setColor(mPaintArcColor); | |||
| mPaintArc.setStrokeWidth(mPaintArcWidth); | |||
| mPaintText = new Paint(Paint.ANTI_ALIAS_FLAG); | |||
| mPaintText.setStyle(Paint.Style.STROKE); | |||
| mPaintText.setStyle(Paint.Style.FILL); | |||
| mPaintText.setAntiAlias(true); | |||
| mPaintText.setColor(mTextColor); | |||
| mPaintText.setTextSize(mTextSize); | |||
| //如果时间为小于0,则默认倒计时时间为3秒 | |||
| if (mLoadingTime < 0) { | |||
| mLoadingTime = 3; | |||
| } | |||
| if (location == 1) {//默认从左侧开始 | |||
| startAngle = -180; | |||
| } else if (location == 2) { | |||
| startAngle = -90; | |||
| } else if (location == 3) { | |||
| startAngle = 0; | |||
| } else if (location == 4) { | |||
| startAngle = 90; | |||
| } | |||
| if (mRetreatType == 1) { | |||
| mmSweepAngleStart = 0f; | |||
| mmSweepAngleEnd = 360f; | |||
| } else { | |||
| mmSweepAngleStart = 360f; | |||
| mmSweepAngleEnd = 0f; | |||
| } | |||
| } | |||
| @Override | |||
| protected void onSizeChanged(int w, int h, int oldw, int oldh) { | |||
| super.onSizeChanged(w, h, oldw, oldh); | |||
| //获取view宽高 | |||
| mWidth = w; | |||
| mHeight = h; | |||
| } | |||
| @Override | |||
| protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |||
| super.onMeasure(widthMeasureSpec, heightMeasureSpec); | |||
| //因为必须是圆形的view,所以在这里重新赋值 | |||
| setMeasuredDimension(mCircleRadius * 2, mCircleRadius * 2); | |||
| } | |||
| @Override | |||
| protected void onDraw(Canvas canvas) { | |||
| super.onDraw(canvas); | |||
| //画北景园 | |||
| canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2 - mPaintArcWidth, mPaintBackGround); | |||
| //画圆弧 | |||
| RectF rectF = new RectF(0 + mPaintArcWidth / 2, 0 + mPaintArcWidth / 2, mWidth - mPaintArcWidth / 2, mHeight - mPaintArcWidth / 2); | |||
| canvas.drawArc(rectF, startAngle, mSweepAngle, false, mPaintArc); | |||
| //画文字 | |||
| float mTextWidth = mPaintText.measureText(mText, 0, mText.length()); | |||
| float dx = mWidth / 2 - mTextWidth / 2; | |||
| Paint.FontMetricsInt fontMetricsInt = mPaintText.getFontMetricsInt(); | |||
| float dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom; | |||
| float baseLine = mHeight / 2 + dy; | |||
| canvas.drawText(mText, dx, baseLine, mPaintText); | |||
| } | |||
| /** | |||
| * 开始动态倒计时 | |||
| */ | |||
| public void start() { | |||
| ValueAnimator animator = ValueAnimator.ofFloat(mmSweepAngleStart, mmSweepAngleEnd); | |||
| animator.setInterpolator(new LinearInterpolator()); | |||
| animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { | |||
| @Override | |||
| public void onAnimationUpdate(ValueAnimator valueAnimator) { | |||
| mSweepAngle = (float) valueAnimator.getAnimatedValue(); | |||
| //获取到需要绘制的角度,重新绘制 | |||
| invalidate(); | |||
| } | |||
| }); | |||
| //这里是时间获取和赋值 | |||
| ValueAnimator animator1 = ValueAnimator.ofInt(mLoadingTime, 0); | |||
| animator1.setInterpolator(new LinearInterpolator()); | |||
| animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { | |||
| @Override | |||
| public void onAnimationUpdate(ValueAnimator valueAnimator) { | |||
| int time = (int) valueAnimator.getAnimatedValue(); | |||
| mText = time + mLoadingTimeUnit; | |||
| } | |||
| }); | |||
| set = new AnimatorSet(); | |||
| set.playTogether(animator, animator1); | |||
| set.setDuration(mLoadingTime * 1000); | |||
| set.setInterpolator(new LinearInterpolator()); | |||
| set.start(); | |||
| set.addListener(new AnimatorListenerAdapter() { | |||
| @Override | |||
| public void onAnimationEnd(Animator animation) { | |||
| super.onAnimationEnd(animation); | |||
| clearAnimation(); | |||
| if (loadingFinishListener != null) { | |||
| loadingFinishListener.finish(); | |||
| } | |||
| } | |||
| }); | |||
| } | |||
| /** | |||
| * 停止动画 | |||
| */ | |||
| public void stop() { | |||
| loadingFinishListener = null; | |||
| if (set != null && set.isRunning()) { | |||
| set.cancel(); | |||
| } | |||
| } | |||
| /** | |||
| * 设置倒计时时间 | |||
| * | |||
| * @param time 时间,秒 | |||
| */ | |||
| public void setTime(int time) { | |||
| mLoadingTime = time; | |||
| } | |||
| private OnLoadingFinishListener loadingFinishListener; | |||
| public void setOnLoadingFinishListener(OnLoadingFinishListener listener) { | |||
| this.loadingFinishListener = listener; | |||
| } | |||
| public interface OnLoadingFinishListener { | |||
| void finish(); | |||
| } | |||
| /** | |||
| * 根据手机的分辨率从 dp 的单位 转成为 px(像素) | |||
| */ | |||
| public static int dip2px(Context context, float dpValue) { | |||
| final float scale = context.getResources().getDisplayMetrics().density; | |||
| return (int) (dpValue * scale + 0.5f); | |||
| } | |||
| } | |||
| @@ -0,0 +1,227 @@ | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * <p> | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * <p> | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * <p> | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package com.mindspore.customview.countdown; | |||
| import android.animation.Animator; | |||
| import android.animation.AnimatorListenerAdapter; | |||
| import android.animation.AnimatorSet; | |||
| import android.animation.ValueAnimator; | |||
| import android.annotation.TargetApi; | |||
| import android.content.Context; | |||
| import android.content.res.TypedArray; | |||
| import android.graphics.Canvas; | |||
| import android.graphics.Color; | |||
| import android.graphics.Paint; | |||
| import android.graphics.RectF; | |||
| import android.os.Build; | |||
| import android.text.TextUtils; | |||
| import android.util.AttributeSet; | |||
| import android.view.View; | |||
| import android.view.animation.LinearInterpolator; | |||
| import androidx.annotation.Nullable; | |||
| import androidx.core.content.ContextCompat; | |||
| import com.mindspore.common.utils.DisplayUtil; | |||
| import com.mindspore.customview.R; | |||
| public class MSCountDownView extends View { | |||
| private static final int HALF = 2; | |||
| private Context mContext; | |||
| private Paint mPaintBackGround, mPaintArc, mPaintText; | |||
| private int mRetreatType; | |||
| private float mPaintArcWidth; | |||
| private int mCircleRadius; | |||
| private int mPaintArcColor = Color.RED; | |||
| private int mPaintBackGroundColor = Color.BLUE; | |||
| private int mLoadingTime; | |||
| private String mLoadingTimeUnit = ""; | |||
| private int mTextColor = Color.BLACK; | |||
| private int mTextSize; | |||
| private int location; | |||
| private float startAngle, mmSweepAngleStart, mmSweepAngleEnd, mSweepAngle; | |||
| private String mText = ""; | |||
| private int mWidth, mHeight; | |||
| private AnimatorSet set; | |||
| public MSCountDownView(Context context) { | |||
| this(context, null); | |||
| } | |||
| public MSCountDownView(Context context, @Nullable AttributeSet attrs) { | |||
| this(context, attrs, 0); | |||
| } | |||
| public MSCountDownView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { | |||
| super(context, attrs, defStyleAttr); | |||
| mContext = context; | |||
| init(attrs); | |||
| initView(); | |||
| } | |||
| private void init(AttributeSet attrs) { | |||
| TypedArray array = mContext.obtainStyledAttributes(attrs, R.styleable.MSCountDownView); | |||
| mRetreatType = array.getInt(R.styleable.MSCountDownView_ms_cd_retreat_type, 1); | |||
| location = array.getInt(R.styleable.MSCountDownView_ms_cd_location, 1); | |||
| mCircleRadius = (int) array.getDimension(R.styleable.MSCountDownView_ms_cd_circle_radius, DisplayUtil.dp2px(mContext, 25)); | |||
| mPaintArcWidth = array.getDimension(R.styleable.MSCountDownView_ms_cd_arc_width, DisplayUtil.dp2px(mContext, 3)); | |||
| mPaintArcColor = array.getColor(R.styleable.MSCountDownView_ms_cd_arc_color, mPaintArcColor); | |||
| mTextSize = (int) array.getDimension(R.styleable.MSCountDownView_ms_cd_text_size, DisplayUtil.dp2px(mContext, 14)); | |||
| mTextColor = array.getColor(R.styleable.MSCountDownView_ms_cd_text_color, mTextColor); | |||
| mPaintBackGroundColor = array.getColor(R.styleable.MSCountDownView_ms_cd_bg_color, mPaintBackGroundColor); | |||
| mLoadingTime = array.getInteger(R.styleable.MSCountDownView_ms_cd_animator_time, 3); | |||
| mLoadingTimeUnit = array.getString(R.styleable.MSCountDownView_ms_cd_animator_time_unit); | |||
| if (TextUtils.isEmpty(mLoadingTimeUnit)) { | |||
| mLoadingTimeUnit = ""; | |||
| } | |||
| array.recycle(); | |||
| } | |||
| @TargetApi(Build.VERSION_CODES.JELLY_BEAN) | |||
| private void initView() { | |||
| this.setBackground(ContextCompat.getDrawable(mContext, android.R.color.transparent)); | |||
| mPaintBackGround = new Paint(); | |||
| mPaintBackGround.setAntiAlias(true); | |||
| mPaintBackGround.setStyle(Paint.Style.FILL); | |||
| mPaintBackGround.setColor(mPaintBackGroundColor); | |||
| mPaintArc = new Paint(); | |||
| mPaintArc.setAntiAlias(true); | |||
| mPaintArc.setStyle(Paint.Style.STROKE); | |||
| mPaintArc.setColor(mPaintArcColor); | |||
| mPaintArc.setStrokeWidth(mPaintArcWidth); | |||
| mPaintText = new Paint(Paint.ANTI_ALIAS_FLAG); | |||
| mPaintText.setAntiAlias(true); | |||
| mPaintText.setStyle(Paint.Style.STROKE); | |||
| mPaintText.setStyle(Paint.Style.FILL); | |||
| mPaintText.setColor(mTextColor); | |||
| mPaintText.setTextSize(mTextSize); | |||
| if (mLoadingTime < 0) { | |||
| mLoadingTime = 3; | |||
| } | |||
| switch (location) { | |||
| case 1: | |||
| startAngle = -180; | |||
| break; | |||
| case 2: | |||
| startAngle = -90; | |||
| break; | |||
| case 3: | |||
| startAngle = 0; | |||
| break; | |||
| case 4: | |||
| startAngle = 90; | |||
| break; | |||
| } | |||
| if (mRetreatType == 1) { | |||
| mmSweepAngleStart = 0f; | |||
| mmSweepAngleEnd = 360f; | |||
| } else { | |||
| mmSweepAngleStart = 360f; | |||
| mmSweepAngleEnd = 0f; | |||
| } | |||
| } | |||
| @Override | |||
| protected void onSizeChanged(int w, int h, int oldw, int oldh) { | |||
| super.onSizeChanged(w, h, oldw, oldh); | |||
| mWidth = w; | |||
| mHeight = h; | |||
| } | |||
| @Override | |||
| protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |||
| super.onMeasure(widthMeasureSpec, heightMeasureSpec); | |||
| setMeasuredDimension(mCircleRadius * HALF, mCircleRadius * HALF); | |||
| } | |||
| @Override | |||
| protected void onDraw(Canvas canvas) { | |||
| super.onDraw(canvas); | |||
| canvas.drawCircle(mWidth / HALF, mHeight / HALF, mWidth / HALF - mPaintArcWidth, mPaintBackGround); | |||
| RectF rectF = new RectF( mPaintArcWidth / HALF, mPaintArcWidth / HALF, mWidth - mPaintArcWidth / HALF, mHeight - mPaintArcWidth / HALF); | |||
| canvas.drawArc(rectF, startAngle, mSweepAngle, false, mPaintArc); | |||
| float mTextWidth = mPaintText.measureText(mText, 0, mText.length()); | |||
| float dx = mWidth / HALF - mTextWidth / HALF; | |||
| Paint.FontMetricsInt fontMetricsInt = mPaintText.getFontMetricsInt(); | |||
| float dy = (fontMetricsInt.bottom - fontMetricsInt.top) / HALF - fontMetricsInt.bottom; | |||
| float baseLine = mHeight / HALF + dy; | |||
| canvas.drawText(mText, dx, baseLine, mPaintText); | |||
| } | |||
| public void start() { | |||
| ValueAnimator viewAnimator = ValueAnimator.ofFloat(mmSweepAngleStart, mmSweepAngleEnd); | |||
| viewAnimator.setInterpolator(new LinearInterpolator()); | |||
| viewAnimator.addUpdateListener(valueAnimator -> { | |||
| mSweepAngle = (float) valueAnimator.getAnimatedValue(); | |||
| invalidate(); | |||
| }); | |||
| ValueAnimator textAnimator = ValueAnimator.ofInt(mLoadingTime, 0); | |||
| textAnimator.setInterpolator(new LinearInterpolator()); | |||
| textAnimator.addUpdateListener(valueAnimator -> { | |||
| int time = (int) valueAnimator.getAnimatedValue(); | |||
| mText = time + mLoadingTimeUnit; | |||
| }); | |||
| set = new AnimatorSet(); | |||
| set.setDuration(mLoadingTime * 1000); | |||
| set.playTogether(viewAnimator, textAnimator); | |||
| set.setInterpolator(new LinearInterpolator()); | |||
| set.start(); | |||
| set.addListener(new AnimatorListenerAdapter() { | |||
| @Override | |||
| public void onAnimationEnd(Animator animation) { | |||
| super.onAnimationEnd(animation); | |||
| clearAnimation(); | |||
| if (onCountDownFinishListener != null) { | |||
| onCountDownFinishListener.finish(); | |||
| } | |||
| } | |||
| }); | |||
| } | |||
| public void stop() { | |||
| onCountDownFinishListener = null; | |||
| if (set != null && set.isRunning()) { | |||
| set.cancel(); | |||
| } | |||
| } | |||
| public void setTime(int time) { | |||
| mLoadingTime = time; | |||
| } | |||
| private OnCountDownFinishListener onCountDownFinishListener; | |||
| public void setOnLoadingFinishListener(OnCountDownFinishListener listener) { | |||
| this.onCountDownFinishListener = listener; | |||
| } | |||
| public interface OnCountDownFinishListener { | |||
| void finish(); | |||
| } | |||
| } | |||
| @@ -1,943 +0,0 @@ | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * <p> | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * <p> | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * <p> | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package com.mindspore.customview.tablayout; | |||
| import android.animation.TypeEvaluator; | |||
| import android.animation.ValueAnimator; | |||
| 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.view.animation.OvershootInterpolator; | |||
| import android.widget.FrameLayout; | |||
| import android.widget.ImageView; | |||
| import android.widget.LinearLayout; | |||
| import android.widget.TextView; | |||
| import androidx.fragment.app.Fragment; | |||
| import androidx.fragment.app.FragmentActivity; | |||
| import com.mindspore.common.utils.DisplayUtil; | |||
| import com.mindspore.customview.R; | |||
| import com.mindspore.customview.tablayout.listener.CustomTabEntity; | |||
| import com.mindspore.customview.tablayout.listener.OnTabSelectListener; | |||
| import com.mindspore.customview.tablayout.utils.FragmentChangeManager; | |||
| import com.mindspore.customview.tablayout.utils.UnreadMsgUtils; | |||
| import com.mindspore.customview.tablayout.widget.MsgView; | |||
| import java.util.ArrayList; | |||
| 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 final Rect mIndicatorRect = new Rect(); | |||
| private final 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); | |||
| } | |||
| public CommonTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { | |||
| super(context, attrs, defStyleAttr); | |||
| setWillNotDraw(false); | |||
| 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, | |||
| DisplayUtil.dp2px(context, mIndicatorStyle == STYLE_TRIANGLE ? 4 : (mIndicatorStyle == STYLE_BLOCK ? -1 : 2))); | |||
| mIndicatorWidth = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_width, DisplayUtil.dp2px(context, mIndicatorStyle == STYLE_TRIANGLE ? 10 : -1)); | |||
| mIndicatorCornerRadius = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_corner_radius, DisplayUtil.dp2px(context, mIndicatorStyle == STYLE_BLOCK ? -1 : 0)); | |||
| mIndicatorMarginLeft = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_margin_left, DisplayUtil.dp2px(context, 0)); | |||
| mIndicatorMarginTop = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_margin_top, DisplayUtil.dp2px(context, mIndicatorStyle == STYLE_BLOCK ? 7 : 0)); | |||
| mIndicatorMarginRight = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_margin_right, DisplayUtil.dp2px(context, 0)); | |||
| mIndicatorMarginBottom = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_margin_bottom, DisplayUtil.dp2px(context, 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, DisplayUtil.dp2px(context, 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, DisplayUtil.dp2px(context, 0)); | |||
| mDividerPadding = ta.getDimension(R.styleable.CommonTabLayout_tl_divider_padding, DisplayUtil.dp2px(context, 12)); | |||
| mTextsize = ta.getDimension(R.styleable.CommonTabLayout_tl_textsize, DisplayUtil.sp2px(context, 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, DisplayUtil.dp2px(context, 0)); | |||
| mIconHeight = ta.getDimension(R.styleable.CommonTabLayout_tl_iconHeight, DisplayUtil.dp2px(context, 0)); | |||
| mIconMargin = ta.getDimension(R.styleable.CommonTabLayout_tl_iconMargin, DisplayUtil.dp2px(context, 2.5f)); | |||
| mTabSpaceEqual = ta.getBoolean(R.styleable.CommonTabLayout_tl_tab_space_equal, true); | |||
| mTabWidth = ta.getDimension(R.styleable.CommonTabLayout_tl_tab_width, DisplayUtil.dp2px(context, -1)); | |||
| mTabPadding = ta.getDimension(R.styleable.CommonTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? DisplayUtil.dp2px(context, 0) : DisplayUtil.dp2px(context, 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(); | |||
| } | |||
| 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(); | |||
| } | |||
| private void addTab(final int position, View tabView) { | |||
| TextView tv_tab_title = tabView.findViewById(R.id.tv_tab_title); | |||
| tv_tab_title.setText(mTabEntitys.get(position).getTabTitle()); | |||
| ImageView iv_tab_icon = tabView.findViewById(R.id.iv_tab_icon); | |||
| iv_tab_icon.setImageResource(mTabEntitys.get(position).getTabUnselectedIcon()); | |||
| tabView.setOnClickListener(v -> { | |||
| int position1 = (Integer) v.getTag(); | |||
| if (mCurrentTab != position1) { | |||
| setCurrentTab(position1); | |||
| if (mListener != null) { | |||
| mListener.onTabSelect(position1); | |||
| } | |||
| } else { | |||
| if (mListener != null) { | |||
| mListener.onTabReselect(position1); | |||
| } | |||
| } | |||
| }); | |||
| 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); | |||
| 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(); | |||
| 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) { | |||
| } else { | |||
| 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) { | |||
| } else { | |||
| 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 { | |||
| 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 = DisplayUtil.dp2px(mContext, tabPadding); | |||
| updateTabStyles(); | |||
| } | |||
| public void setTabSpaceEqual(boolean tabSpaceEqual) { | |||
| this.mTabSpaceEqual = tabSpaceEqual; | |||
| updateTabStyles(); | |||
| } | |||
| public void setTabWidth(float tabWidth) { | |||
| this.mTabWidth = DisplayUtil.dp2px(mContext, tabWidth); | |||
| updateTabStyles(); | |||
| } | |||
| public void setIndicatorColor(int indicatorColor) { | |||
| this.mIndicatorColor = indicatorColor; | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorHeight(float indicatorHeight) { | |||
| this.mIndicatorHeight = DisplayUtil.dp2px(mContext, indicatorHeight); | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorWidth(float indicatorWidth) { | |||
| this.mIndicatorWidth = DisplayUtil.dp2px(mContext, indicatorWidth); | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorCornerRadius(float indicatorCornerRadius) { | |||
| this.mIndicatorCornerRadius = DisplayUtil.dp2px(mContext, indicatorCornerRadius); | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorGravity(int indicatorGravity) { | |||
| this.mIndicatorGravity = indicatorGravity; | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorMargin(float indicatorMarginLeft, float indicatorMarginTop, | |||
| float indicatorMarginRight, float indicatorMarginBottom) { | |||
| this.mIndicatorMarginLeft = DisplayUtil.dp2px(mContext, indicatorMarginLeft); | |||
| this.mIndicatorMarginTop = DisplayUtil.dp2px(mContext, indicatorMarginTop); | |||
| this.mIndicatorMarginRight = DisplayUtil.dp2px(mContext, indicatorMarginRight); | |||
| this.mIndicatorMarginBottom = DisplayUtil.dp2px(mContext, 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 = DisplayUtil.dp2px(mContext, 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 = DisplayUtil.dp2px(mContext, dividerWidth); | |||
| invalidate(); | |||
| } | |||
| public void setDividerPadding(float dividerPadding) { | |||
| this.mDividerPadding = DisplayUtil.dp2px(mContext, dividerPadding); | |||
| invalidate(); | |||
| } | |||
| public void setTextsize(float textsize) { | |||
| this.mTextsize = DisplayUtil.sp2px(mContext, 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 = DisplayUtil.dp2px(mContext, iconWidth); | |||
| updateTabStyles(); | |||
| } | |||
| public void setIconHeight(float iconHeight) { | |||
| this.mIconHeight = DisplayUtil.dp2px(mContext, iconHeight); | |||
| updateTabStyles(); | |||
| } | |||
| public void setIconMargin(float iconMargin) { | |||
| this.mIconMargin = DisplayUtil.dp2px(mContext, 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; | |||
| } | |||
| // show MsgTipView | |||
| private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); | |||
| private SparseArray<Boolean> mInitSetMap = new SparseArray<>(); | |||
| 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); | |||
| } | |||
| } | |||
| 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); | |||
| } | |||
| } | |||
| 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 = DisplayUtil.dp2px(mContext, leftPadding); | |||
| lp.topMargin = mHeight > 0 ? (int) (mHeight - textHeight - iconH - margin) / 2 - DisplayUtil.dp2px(mContext, bottomPadding) : DisplayUtil.dp2px(mContext, bottomPadding); | |||
| } else { | |||
| lp.leftMargin = DisplayUtil.dp2px(mContext, leftPadding); | |||
| lp.topMargin = mHeight > 0 ? (int) (mHeight - Math.max(textHeight, iconH)) / 2 - DisplayUtil.dp2px(mContext, bottomPadding) : DisplayUtil.dp2px(mContext, bottomPadding); | |||
| } | |||
| tipView.setLayoutParams(lp); | |||
| } | |||
| } | |||
| 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; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,749 +0,0 @@ | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * <p> | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * <p> | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * <p> | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package com.mindspore.customview.tablayout; | |||
| import android.animation.TypeEvaluator; | |||
| import android.animation.ValueAnimator; | |||
| import android.content.Context; | |||
| import android.content.res.TypedArray; | |||
| import android.graphics.Canvas; | |||
| import android.graphics.Color; | |||
| import android.graphics.Paint; | |||
| 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.View; | |||
| import android.view.ViewGroup; | |||
| import android.view.animation.OvershootInterpolator; | |||
| import android.widget.FrameLayout; | |||
| import android.widget.LinearLayout; | |||
| import android.widget.TextView; | |||
| import androidx.fragment.app.Fragment; | |||
| import androidx.fragment.app.FragmentActivity; | |||
| import com.mindspore.common.utils.DisplayUtil; | |||
| import com.mindspore.customview.R; | |||
| import com.mindspore.customview.tablayout.listener.OnTabSelectListener; | |||
| import com.mindspore.customview.tablayout.utils.FragmentChangeManager; | |||
| import com.mindspore.customview.tablayout.utils.UnreadMsgUtils; | |||
| import com.mindspore.customview.tablayout.widget.MsgView; | |||
| import java.util.ArrayList; | |||
| public class SegmentTabLayout extends FrameLayout implements ValueAnimator.AnimatorUpdateListener { | |||
| private Context mContext; | |||
| private String[] mTitles; | |||
| private LinearLayout mTabsContainer; | |||
| private int mCurrentTab; | |||
| private int mLastTab; | |||
| private int mTabCount; | |||
| private Rect mIndicatorRect = new Rect(); | |||
| private GradientDrawable mIndicatorDrawable = new GradientDrawable(); | |||
| private GradientDrawable mRectDrawable = new GradientDrawable(); | |||
| private Paint mDividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); | |||
| private float mTabPadding; | |||
| private boolean mTabSpaceEqual; | |||
| private float mTabWidth; | |||
| /** | |||
| * indicator | |||
| */ | |||
| private int mIndicatorColor; | |||
| private float mIndicatorHeight; | |||
| private float mIndicatorCornerRadius; | |||
| private float mIndicatorMarginLeft; | |||
| private float mIndicatorMarginTop; | |||
| private float mIndicatorMarginRight; | |||
| private float mIndicatorMarginBottom; | |||
| private long mIndicatorAnimDuration; | |||
| private boolean mIndicatorAnimEnable; | |||
| private boolean mIndicatorBounceEnable; | |||
| /** | |||
| * 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; | |||
| private int mBarColor; | |||
| private int mBarStrokeColor; | |||
| private float mBarStrokeWidth; | |||
| private int mHeight; | |||
| /** | |||
| * anim | |||
| */ | |||
| private ValueAnimator mValueAnimator; | |||
| private OvershootInterpolator mInterpolator = new OvershootInterpolator(0.8f); | |||
| private FragmentChangeManager mFragmentChangeManager; | |||
| private float[] mRadiusArr = new float[8]; | |||
| public SegmentTabLayout(Context context) { | |||
| this(context, null, 0); | |||
| } | |||
| public SegmentTabLayout(Context context, AttributeSet attrs) { | |||
| this(context, attrs, 0); | |||
| } | |||
| public SegmentTabLayout(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.SegmentTabLayout); | |||
| mIndicatorColor = ta.getColor(R.styleable.SegmentTabLayout_tl_indicator_color, Color.parseColor("#222831")); | |||
| mIndicatorHeight = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_height, -1); | |||
| mIndicatorCornerRadius = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_corner_radius, -1); | |||
| mIndicatorMarginLeft = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_margin_left, DisplayUtil.dp2px(context, 0)); | |||
| mIndicatorMarginTop = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_margin_top, 0); | |||
| mIndicatorMarginRight = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_margin_right, DisplayUtil.dp2px(context, 0)); | |||
| mIndicatorMarginBottom = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_margin_bottom, 0); | |||
| mIndicatorAnimEnable = ta.getBoolean(R.styleable.SegmentTabLayout_tl_indicator_anim_enable, false); | |||
| mIndicatorBounceEnable = ta.getBoolean(R.styleable.SegmentTabLayout_tl_indicator_bounce_enable, true); | |||
| mIndicatorAnimDuration = ta.getInt(com.mindspore.customview.R.styleable.SegmentTabLayout_tl_indicator_anim_duration, -1); | |||
| mDividerColor = ta.getColor(R.styleable.SegmentTabLayout_tl_divider_color, mIndicatorColor); | |||
| mDividerWidth = ta.getDimension(R.styleable.SegmentTabLayout_tl_divider_width, DisplayUtil.dp2px(context, 1)); | |||
| mDividerPadding = ta.getDimension(R.styleable.SegmentTabLayout_tl_divider_padding, 0); | |||
| mTextsize = ta.getDimension(R.styleable.SegmentTabLayout_tl_textsize, DisplayUtil.sp2px(context, 13f)); | |||
| mTextSelectColor = ta.getColor(R.styleable.SegmentTabLayout_tl_textSelectColor, Color.parseColor("#ffffff")); | |||
| mTextUnselectColor = ta.getColor(R.styleable.SegmentTabLayout_tl_textUnselectColor, mIndicatorColor); | |||
| mTextBold = ta.getInt(R.styleable.SegmentTabLayout_tl_textBold, TEXT_BOLD_NONE); | |||
| mTextAllCaps = ta.getBoolean(R.styleable.SegmentTabLayout_tl_textAllCaps, false); | |||
| mTabSpaceEqual = ta.getBoolean(R.styleable.SegmentTabLayout_tl_tab_space_equal, true); | |||
| mTabWidth = ta.getDimension(R.styleable.SegmentTabLayout_tl_tab_width, DisplayUtil.dp2px(context, -1)); | |||
| mTabPadding = ta.getDimension(R.styleable.SegmentTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? DisplayUtil.dp2px(context, 0) : DisplayUtil.dp2px(context, 10)); | |||
| mBarColor = ta.getColor(R.styleable.SegmentTabLayout_tl_bar_color, Color.TRANSPARENT); | |||
| mBarStrokeColor = ta.getColor(R.styleable.SegmentTabLayout_tl_bar_stroke_color, mIndicatorColor); | |||
| mBarStrokeWidth = ta.getDimension(R.styleable.SegmentTabLayout_tl_bar_stroke_width, DisplayUtil.dp2px(context, 1)); | |||
| ta.recycle(); | |||
| } | |||
| public void setTabData(String[] titles) { | |||
| if (titles == null || titles.length == 0) { | |||
| throw new IllegalStateException("Titles can not be NULL or EMPTY !"); | |||
| } | |||
| this.mTitles = titles; | |||
| notifyDataSetChanged(); | |||
| } | |||
| public void setTabData(String[] titles, FragmentActivity fa, int containerViewId, ArrayList<Fragment> fragments) { | |||
| mFragmentChangeManager = new FragmentChangeManager(fa.getSupportFragmentManager(), containerViewId, fragments); | |||
| setTabData(titles); | |||
| } | |||
| public void notifyDataSetChanged() { | |||
| mTabsContainer.removeAllViews(); | |||
| this.mTabCount = mTitles.length; | |||
| View tabView; | |||
| for (int i = 0; i < mTabCount; i++) { | |||
| tabView = View.inflate(mContext, R.layout.layout_tab_segment, null); | |||
| tabView.setTag(i); | |||
| addTab(i, tabView); | |||
| } | |||
| updateTabStyles(); | |||
| } | |||
| private void addTab(final int position, View tabView) { | |||
| TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); | |||
| tv_tab_title.setText(mTitles[position]); | |||
| 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); | |||
| 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); | |||
| } | |||
| } | |||
| } | |||
| 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); | |||
| 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(); | |||
| 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 (!mIndicatorAnimEnable) { | |||
| if (mCurrentTab == 0) { | |||
| /**The corners are ordered top-left, top-right, bottom-right, bottom-left*/ | |||
| mRadiusArr[0] = mIndicatorCornerRadius; | |||
| mRadiusArr[1] = mIndicatorCornerRadius; | |||
| mRadiusArr[2] = 0; | |||
| mRadiusArr[3] = 0; | |||
| mRadiusArr[4] = 0; | |||
| mRadiusArr[5] = 0; | |||
| mRadiusArr[6] = mIndicatorCornerRadius; | |||
| mRadiusArr[7] = mIndicatorCornerRadius; | |||
| } else if (mCurrentTab == mTabCount - 1) { | |||
| /**The corners are ordered top-left, top-right, bottom-right, bottom-left*/ | |||
| mRadiusArr[0] = 0; | |||
| mRadiusArr[1] = 0; | |||
| mRadiusArr[2] = mIndicatorCornerRadius; | |||
| mRadiusArr[3] = mIndicatorCornerRadius; | |||
| mRadiusArr[4] = mIndicatorCornerRadius; | |||
| mRadiusArr[5] = mIndicatorCornerRadius; | |||
| mRadiusArr[6] = 0; | |||
| mRadiusArr[7] = 0; | |||
| } else { | |||
| /**The corners are ordered top-left, top-right, bottom-right, bottom-left*/ | |||
| mRadiusArr[0] = 0; | |||
| mRadiusArr[1] = 0; | |||
| mRadiusArr[2] = 0; | |||
| mRadiusArr[3] = 0; | |||
| mRadiusArr[4] = 0; | |||
| mRadiusArr[5] = 0; | |||
| mRadiusArr[6] = 0; | |||
| mRadiusArr[7] = 0; | |||
| } | |||
| } else { | |||
| /**The corners are ordered top-left, top-right, bottom-right, bottom-left*/ | |||
| mRadiusArr[0] = mIndicatorCornerRadius; | |||
| mRadiusArr[1] = mIndicatorCornerRadius; | |||
| mRadiusArr[2] = mIndicatorCornerRadius; | |||
| mRadiusArr[3] = mIndicatorCornerRadius; | |||
| mRadiusArr[4] = mIndicatorCornerRadius; | |||
| mRadiusArr[5] = mIndicatorCornerRadius; | |||
| mRadiusArr[6] = mIndicatorCornerRadius; | |||
| mRadiusArr[7] = mIndicatorCornerRadius; | |||
| } | |||
| } | |||
| @Override | |||
| public void onAnimationUpdate(ValueAnimator animation) { | |||
| IndicatorPoint p = (IndicatorPoint) animation.getAnimatedValue(); | |||
| mIndicatorRect.left = (int) p.left; | |||
| mIndicatorRect.right = (int) p.right; | |||
| 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(); | |||
| if (mIndicatorHeight < 0) { | |||
| mIndicatorHeight = height - mIndicatorMarginTop - mIndicatorMarginBottom; | |||
| } | |||
| if (mIndicatorCornerRadius < 0 || mIndicatorCornerRadius > mIndicatorHeight / 2) { | |||
| mIndicatorCornerRadius = mIndicatorHeight / 2; | |||
| } | |||
| //draw rect | |||
| mRectDrawable.setColor(mBarColor); | |||
| mRectDrawable.setStroke((int) mBarStrokeWidth, mBarStrokeColor); | |||
| mRectDrawable.setCornerRadius(mIndicatorCornerRadius); | |||
| mRectDrawable.setBounds(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()); | |||
| mRectDrawable.draw(canvas); | |||
| // draw divider | |||
| if (!mIndicatorAnimEnable && 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 indicator line | |||
| if (mIndicatorAnimEnable) { | |||
| if (mIsFirstDraw) { | |||
| mIsFirstDraw = false; | |||
| calcIndicatorRect(); | |||
| } | |||
| } else { | |||
| calcIndicatorRect(); | |||
| } | |||
| mIndicatorDrawable.setColor(mIndicatorColor); | |||
| mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, | |||
| (int) mIndicatorMarginTop, (int) (paddingLeft + mIndicatorRect.right - mIndicatorMarginRight), | |||
| (int) (mIndicatorMarginTop + mIndicatorHeight)); | |||
| mIndicatorDrawable.setCornerRadii(mRadiusArr); | |||
| 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 setTabPadding(float tabPadding) { | |||
| this.mTabPadding = DisplayUtil.dp2px(mContext, tabPadding); | |||
| updateTabStyles(); | |||
| } | |||
| public void setTabSpaceEqual(boolean tabSpaceEqual) { | |||
| this.mTabSpaceEqual = tabSpaceEqual; | |||
| updateTabStyles(); | |||
| } | |||
| public void setTabWidth(float tabWidth) { | |||
| this.mTabWidth = DisplayUtil.dp2px(mContext, tabWidth); | |||
| updateTabStyles(); | |||
| } | |||
| public void setIndicatorColor(int indicatorColor) { | |||
| this.mIndicatorColor = indicatorColor; | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorHeight(float indicatorHeight) { | |||
| this.mIndicatorHeight = DisplayUtil.dp2px(mContext, indicatorHeight); | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorCornerRadius(float indicatorCornerRadius) { | |||
| this.mIndicatorCornerRadius = DisplayUtil.dp2px(mContext, indicatorCornerRadius); | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorMargin(float indicatorMarginLeft, float indicatorMarginTop, | |||
| float indicatorMarginRight, float indicatorMarginBottom) { | |||
| this.mIndicatorMarginLeft = DisplayUtil.dp2px(mContext, indicatorMarginLeft); | |||
| this.mIndicatorMarginTop = DisplayUtil.dp2px(mContext, indicatorMarginTop); | |||
| this.mIndicatorMarginRight = DisplayUtil.dp2px(mContext, indicatorMarginRight); | |||
| this.mIndicatorMarginBottom = DisplayUtil.dp2px(mContext, 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 setDividerColor(int dividerColor) { | |||
| this.mDividerColor = dividerColor; | |||
| invalidate(); | |||
| } | |||
| public void setDividerWidth(float dividerWidth) { | |||
| this.mDividerWidth = DisplayUtil.dp2px(mContext, dividerWidth); | |||
| invalidate(); | |||
| } | |||
| public void setDividerPadding(float dividerPadding) { | |||
| this.mDividerPadding = DisplayUtil.dp2px(mContext, dividerPadding); | |||
| invalidate(); | |||
| } | |||
| public void setTextsize(float textsize) { | |||
| this.mTextsize = DisplayUtil.sp2px(mContext, 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 int getTabCount() { | |||
| return mTabCount; | |||
| } | |||
| public int getCurrentTab() { | |||
| return mCurrentTab; | |||
| } | |||
| 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 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 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(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<>(); | |||
| 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; | |||
| } | |||
| setMsgMargin(position, 2, 2); | |||
| mInitSetMap.put(position, true); | |||
| } | |||
| } | |||
| 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); | |||
| } | |||
| } | |||
| 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(); | |||
| lp.leftMargin = DisplayUtil.dp2px(mContext, leftPadding); | |||
| lp.topMargin = mHeight > 0 ? (int) (mHeight - textHeight) / 2 - DisplayUtil.dp2px(mContext, bottomPadding) : DisplayUtil.dp2px(mContext, bottomPadding); | |||
| tipView.setLayoutParams(lp); | |||
| } | |||
| } | |||
| 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; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,907 +0,0 @@ | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * <p> | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * <p> | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * <p> | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package com.mindspore.customview.tablayout; | |||
| 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.mindspore.common.utils.DisplayUtil; | |||
| import com.mindspore.customview.R; | |||
| import com.mindspore.customview.tablayout.listener.OnTabSelectListener; | |||
| import com.mindspore.customview.tablayout.utils.UnreadMsgUtils; | |||
| import com.mindspore.customview.tablayout.widget.MsgView; | |||
| import java.util.ArrayList; | |||
| import java.util.Collections; | |||
| 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 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); | |||
| 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, R.styleable.SlidingTabLayout); | |||
| mIndicatorStyle = ta.getInt(R.styleable.SlidingTabLayout_tl_indicator_style, STYLE_NORMAL); | |||
| mIndicatorColor = ta.getColor(R.styleable.SlidingTabLayout_tl_indicator_color, Color.parseColor(mIndicatorStyle == STYLE_BLOCK ? "#4B6A87" : "#ffffff")); | |||
| mIndicatorHeight = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_height, | |||
| DisplayUtil.dp2px(context, mIndicatorStyle == STYLE_TRIANGLE ? 4 : (mIndicatorStyle == STYLE_BLOCK ? -1 : 2))); | |||
| mIndicatorWidth = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_width, DisplayUtil.dp2px(context, mIndicatorStyle == STYLE_TRIANGLE ? 10 : -1)); | |||
| mIndicatorCornerRadius = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_corner_radius, DisplayUtil.dp2px(context, mIndicatorStyle == STYLE_BLOCK ? -1 : 0)); | |||
| mIndicatorMarginLeft = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_left, DisplayUtil.dp2px(context, 0)); | |||
| mIndicatorMarginTop = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_top, DisplayUtil.dp2px(context, mIndicatorStyle == STYLE_BLOCK ? 7 : 0)); | |||
| mIndicatorMarginRight = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_right, DisplayUtil.dp2px(context, 0)); | |||
| mIndicatorMarginBottom = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_bottom, DisplayUtil.dp2px(context, mIndicatorStyle == STYLE_BLOCK ? 7 : 0)); | |||
| mIndicatorGravity = ta.getInt(R.styleable.SlidingTabLayout_tl_indicator_gravity, Gravity.BOTTOM); | |||
| mIndicatorWidthEqualTitle = ta.getBoolean(R.styleable.SlidingTabLayout_tl_indicator_width_equal_title, false); | |||
| mUnderlineColor = ta.getColor(R.styleable.SlidingTabLayout_tl_underline_color, Color.parseColor("#ffffff")); | |||
| mUnderlineHeight = ta.getDimension(R.styleable.SlidingTabLayout_tl_underline_height, DisplayUtil.dp2px(context, 0)); | |||
| mUnderlineGravity = ta.getInt(R.styleable.SlidingTabLayout_tl_underline_gravity, Gravity.BOTTOM); | |||
| mDividerColor = ta.getColor(R.styleable.SlidingTabLayout_tl_divider_color, Color.parseColor("#ffffff")); | |||
| mDividerWidth = ta.getDimension(R.styleable.SlidingTabLayout_tl_divider_width, DisplayUtil.dp2px(context, 0)); | |||
| mDividerPadding = ta.getDimension(R.styleable.SlidingTabLayout_tl_divider_padding, DisplayUtil.dp2px(context, 12)); | |||
| mTextsize = ta.getDimension(R.styleable.SlidingTabLayout_tl_textsize, DisplayUtil.sp2px(context, 14)); | |||
| mTextSelectColor = ta.getColor(R.styleable.SlidingTabLayout_tl_textSelectColor, Color.parseColor("#ffffff")); | |||
| mTextUnselectColor = ta.getColor(R.styleable.SlidingTabLayout_tl_textUnselectColor, Color.parseColor("#AAffffff")); | |||
| mTextBold = ta.getInt(R.styleable.SlidingTabLayout_tl_textBold, TEXT_BOLD_NONE); | |||
| mTextAllCaps = ta.getBoolean(R.styleable.SlidingTabLayout_tl_textAllCaps, false); | |||
| mTabSpaceEqual = ta.getBoolean(R.styleable.SlidingTabLayout_tl_tab_space_equal, false); | |||
| mTabWidth = ta.getDimension(R.styleable.SlidingTabLayout_tl_tab_width, DisplayUtil.dp2px(context, -1)); | |||
| mTabPadding = ta.getDimension(R.styleable.SlidingTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? DisplayUtil.dp2px(context, 0) : DisplayUtil.dp2px(context, 20)); | |||
| ta.recycle(); | |||
| } | |||
| 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(); | |||
| } | |||
| 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(); | |||
| } | |||
| 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, 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, 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(); | |||
| } | |||
| private void addTab(final int position, String title, View tabView) { | |||
| TextView tv_tab_title = (TextView) tabView.findViewById(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) { | |||
| 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); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| }); | |||
| 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 v = mTabsContainer.getChildAt(i); | |||
| // v.setPadding((int) mTabPadding, v.getPaddingTop(), (int) mTabPadding, v.getPaddingBottom()); | |||
| TextView tv_tab_title = (TextView) v.findViewById(R.id.tv_tab_title); | |||
| if (tv_tab_title != null) { | |||
| 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); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { | |||
| 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()); | |||
| 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(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(R.id.tv_tab_title); | |||
| if (tab_title != null) { | |||
| tab_title.setTextColor(isSelect ? mTextSelectColor : mTextUnselectColor); | |||
| 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(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(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) { | |||
| } else { | |||
| 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 = DisplayUtil.dp2px(mContext, tabPadding); | |||
| updateTabStyles(); | |||
| } | |||
| public void setTabSpaceEqual(boolean tabSpaceEqual) { | |||
| this.mTabSpaceEqual = tabSpaceEqual; | |||
| updateTabStyles(); | |||
| } | |||
| public void setTabWidth(float tabWidth) { | |||
| this.mTabWidth = DisplayUtil.dp2px(mContext, tabWidth); | |||
| updateTabStyles(); | |||
| } | |||
| public void setIndicatorColor(int indicatorColor) { | |||
| this.mIndicatorColor = indicatorColor; | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorHeight(float indicatorHeight) { | |||
| this.mIndicatorHeight = DisplayUtil.dp2px(mContext, indicatorHeight); | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorWidth(float indicatorWidth) { | |||
| this.mIndicatorWidth = DisplayUtil.dp2px(mContext, indicatorWidth); | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorCornerRadius(float indicatorCornerRadius) { | |||
| this.mIndicatorCornerRadius = DisplayUtil.dp2px(mContext, indicatorCornerRadius); | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorGravity(int indicatorGravity) { | |||
| this.mIndicatorGravity = indicatorGravity; | |||
| invalidate(); | |||
| } | |||
| public void setIndicatorMargin(float indicatorMarginLeft, float indicatorMarginTop, | |||
| float indicatorMarginRight, float indicatorMarginBottom) { | |||
| this.mIndicatorMarginLeft = DisplayUtil.dp2px(mContext, indicatorMarginLeft); | |||
| this.mIndicatorMarginTop = DisplayUtil.dp2px(mContext, indicatorMarginTop); | |||
| this.mIndicatorMarginRight = DisplayUtil.dp2px(mContext, indicatorMarginRight); | |||
| this.mIndicatorMarginBottom = DisplayUtil.dp2px(mContext, 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 = DisplayUtil.dp2px(mContext, 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 = DisplayUtil.dp2px(mContext, dividerWidth); | |||
| invalidate(); | |||
| } | |||
| public void setDividerPadding(float dividerPadding) { | |||
| this.mDividerPadding = DisplayUtil.dp2px(mContext, dividerPadding); | |||
| invalidate(); | |||
| } | |||
| public void setTextsize(float textsize) { | |||
| this.mTextsize = DisplayUtil.sp2px(mContext, 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(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<>(); | |||
| 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; | |||
| } | |||
| setMsgMargin(position, 4, 2); | |||
| mInitSetMap.put(position, true); | |||
| } | |||
| } | |||
| 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); | |||
| } | |||
| } | |||
| 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(); | |||
| lp.leftMargin = mTabWidth >= 0 ? (int) (mTabWidth / 2 + textWidth / 2 + DisplayUtil.dp2px(mContext, leftPadding)) : (int) (mTabPadding + textWidth + DisplayUtil.dp2px(mContext, leftPadding)); | |||
| lp.topMargin = mHeight > 0 ? (int) (mHeight - textHeight) / 2 - DisplayUtil.dp2px(mContext, bottomPadding) : 0; | |||
| tipView.setLayoutParams(lp); | |||
| } | |||
| } | |||
| 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; | |||
| } | |||
| 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); | |||
| } | |||
| } | |||
| @@ -1,21 +0,0 @@ | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * <p> | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * <p> | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * <p> | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package com.mindspore.customview.tablayout.listener; | |||
| public interface OnTabSelectListener { | |||
| void onTabSelect(int position); | |||
| void onTabReselect(int position); | |||
| } | |||
| @@ -1,69 +0,0 @@ | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * <p> | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * <p> | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * <p> | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package com.mindspore.customview.tablayout.utils; | |||
| import androidx.fragment.app.Fragment; | |||
| import androidx.fragment.app.FragmentManager; | |||
| import androidx.fragment.app.FragmentTransaction; | |||
| import java.util.ArrayList; | |||
| public class FragmentChangeManager { | |||
| private FragmentManager mFragmentManager; | |||
| private int mContainerViewId; | |||
| private ArrayList<Fragment> mFragments; | |||
| private int mCurrentTab; | |||
| public FragmentChangeManager(FragmentManager fm, int containerViewId, ArrayList<Fragment> fragments) { | |||
| this.mFragmentManager = fm; | |||
| this.mContainerViewId = containerViewId; | |||
| this.mFragments = fragments; | |||
| initFragments(); | |||
| } | |||
| private void initFragments() { | |||
| for (Fragment fragment : mFragments) { | |||
| mFragmentManager.beginTransaction().add(mContainerViewId, fragment).hide(fragment).commit(); | |||
| } | |||
| setFragments(0); | |||
| } | |||
| public void setFragments(int index) { | |||
| for (int i = 0; i < mFragments.size(); i++) { | |||
| FragmentTransaction ft = mFragmentManager.beginTransaction(); | |||
| Fragment fragment = mFragments.get(i); | |||
| if (i == index) { | |||
| ft.show(fragment); | |||
| } else { | |||
| ft.hide(fragment); | |||
| } | |||
| ft.commit(); | |||
| } | |||
| mCurrentTab = index; | |||
| } | |||
| public int getCurrentTab() { | |||
| return mCurrentTab; | |||
| } | |||
| public Fragment getCurrentFragment() { | |||
| return mFragments.get(mCurrentTab); | |||
| } | |||
| } | |||
| @@ -1,66 +0,0 @@ | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * <p> | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * <p> | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * <p> | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package com.mindspore.customview.tablayout.utils; | |||
| import android.util.DisplayMetrics; | |||
| import android.view.View; | |||
| import android.widget.RelativeLayout; | |||
| import com.mindspore.customview.tablayout.widget.MsgView; | |||
| public class UnreadMsgUtils { | |||
| public static void show(MsgView msgView, int num) { | |||
| if (msgView == null) { | |||
| return; | |||
| } | |||
| RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) msgView.getLayoutParams(); | |||
| DisplayMetrics dm = msgView.getResources().getDisplayMetrics(); | |||
| msgView.setVisibility(View.VISIBLE); | |||
| if (num <= 0) {//圆点,设置默认宽高 | |||
| msgView.setStrokeWidth(0); | |||
| msgView.setText(""); | |||
| lp.width = (int) (5 * dm.density); | |||
| lp.height = (int) (5 * dm.density); | |||
| msgView.setLayoutParams(lp); | |||
| } else { | |||
| lp.height = (int) (18 * dm.density); | |||
| if (num > 0 && num < 10) { | |||
| lp.width = (int) (18 * dm.density); | |||
| msgView.setText(num + ""); | |||
| } else if (num > 9 && num < 100) { | |||
| lp.width = RelativeLayout.LayoutParams.WRAP_CONTENT; | |||
| msgView.setPadding((int) (6 * dm.density), 0, (int) (6 * dm.density), 0); | |||
| msgView.setText(num + ""); | |||
| } else { | |||
| lp.width = RelativeLayout.LayoutParams.WRAP_CONTENT; | |||
| msgView.setPadding((int) (6 * dm.density), 0, (int) (6 * dm.density), 0); | |||
| msgView.setText("99+"); | |||
| } | |||
| msgView.setLayoutParams(lp); | |||
| } | |||
| } | |||
| public static void setSize(MsgView rtv, int size) { | |||
| if (rtv == null) { | |||
| return; | |||
| } | |||
| RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) rtv.getLayoutParams(); | |||
| lp.width = size; | |||
| lp.height = size; | |||
| rtv.setLayoutParams(lp); | |||
| } | |||
| } | |||
| @@ -1,150 +0,0 @@ | |||
| package com.mindspore.customview.tablayout.widget; | |||
| import android.annotation.SuppressLint; | |||
| import android.content.Context; | |||
| import android.content.res.TypedArray; | |||
| import android.graphics.Color; | |||
| import android.graphics.drawable.GradientDrawable; | |||
| import android.graphics.drawable.StateListDrawable; | |||
| import android.os.Build; | |||
| import android.util.AttributeSet; | |||
| import android.widget.TextView; | |||
| import com.mindspore.common.utils.DisplayUtil; | |||
| import com.mindspore.customview.R; | |||
| @SuppressLint("AppCompatCustomView") | |||
| public class MsgView extends TextView { | |||
| private Context context; | |||
| private GradientDrawable gd_background = new GradientDrawable(); | |||
| private int backgroundColor; | |||
| private int cornerRadius; | |||
| private int strokeWidth; | |||
| private int strokeColor; | |||
| private boolean isRadiusHalfHeight; | |||
| private boolean isWidthHeightEqual; | |||
| public MsgView(Context context) { | |||
| this(context, null); | |||
| } | |||
| public MsgView(Context context, AttributeSet attrs) { | |||
| this(context, attrs, 0); | |||
| } | |||
| public MsgView(Context context, AttributeSet attrs, int defStyleAttr) { | |||
| super(context, attrs, defStyleAttr); | |||
| this.context = context; | |||
| obtainAttributes(context, attrs); | |||
| } | |||
| private void obtainAttributes(Context context, AttributeSet attrs) { | |||
| TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MsgView); | |||
| backgroundColor = ta.getColor(R.styleable.MsgView_mv_backgroundColor, Color.TRANSPARENT); | |||
| cornerRadius = ta.getDimensionPixelSize(R.styleable.MsgView_mv_cornerRadius, 0); | |||
| strokeWidth = ta.getDimensionPixelSize(R.styleable.MsgView_mv_strokeWidth, 0); | |||
| strokeColor = ta.getColor(R.styleable.MsgView_mv_strokeColor, Color.TRANSPARENT); | |||
| isRadiusHalfHeight = ta.getBoolean(R.styleable.MsgView_mv_isRadiusHalfHeight, false); | |||
| isWidthHeightEqual = ta.getBoolean(R.styleable.MsgView_mv_isWidthHeightEqual, false); | |||
| ta.recycle(); | |||
| } | |||
| @Override | |||
| protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |||
| if (isWidthHeightEqual() && getWidth() > 0 && getHeight() > 0) { | |||
| int max = Math.max(getWidth(), getHeight()); | |||
| int measureSpec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY); | |||
| super.onMeasure(measureSpec, measureSpec); | |||
| return; | |||
| } | |||
| super.onMeasure(widthMeasureSpec, heightMeasureSpec); | |||
| } | |||
| @Override | |||
| protected void onLayout(boolean changed, int left, int top, int right, int bottom) { | |||
| super.onLayout(changed, left, top, right, bottom); | |||
| if (isRadiusHalfHeight()) { | |||
| setCornerRadius(getHeight() / 2); | |||
| } else { | |||
| setBgSelector(); | |||
| } | |||
| } | |||
| public void setBackgroundColor(int backgroundColor) { | |||
| this.backgroundColor = backgroundColor; | |||
| setBgSelector(); | |||
| } | |||
| public void setCornerRadius(int cornerRadius) { | |||
| this.cornerRadius = DisplayUtil.dp2px(context, cornerRadius); | |||
| setBgSelector(); | |||
| } | |||
| public void setStrokeWidth(int strokeWidth) { | |||
| this.strokeWidth = DisplayUtil.dp2px(context, strokeWidth); | |||
| setBgSelector(); | |||
| } | |||
| public void setStrokeColor(int strokeColor) { | |||
| this.strokeColor = strokeColor; | |||
| setBgSelector(); | |||
| } | |||
| public void setIsRadiusHalfHeight(boolean isRadiusHalfHeight) { | |||
| this.isRadiusHalfHeight = isRadiusHalfHeight; | |||
| setBgSelector(); | |||
| } | |||
| public void setIsWidthHeightEqual(boolean isWidthHeightEqual) { | |||
| this.isWidthHeightEqual = isWidthHeightEqual; | |||
| setBgSelector(); | |||
| } | |||
| public int getBackgroundColor() { | |||
| return backgroundColor; | |||
| } | |||
| public int getCornerRadius() { | |||
| return cornerRadius; | |||
| } | |||
| public int getStrokeWidth() { | |||
| return strokeWidth; | |||
| } | |||
| public int getStrokeColor() { | |||
| return strokeColor; | |||
| } | |||
| public boolean isRadiusHalfHeight() { | |||
| return isRadiusHalfHeight; | |||
| } | |||
| public boolean isWidthHeightEqual() { | |||
| return isWidthHeightEqual; | |||
| } | |||
| private void setDrawable(GradientDrawable gd, int color, int strokeColor) { | |||
| gd.setColor(color); | |||
| gd.setCornerRadius(cornerRadius); | |||
| gd.setStroke(strokeWidth, strokeColor); | |||
| } | |||
| public void setBgSelector() { | |||
| StateListDrawable bg = new StateListDrawable(); | |||
| setDrawable(gd_background, backgroundColor, strokeColor); | |||
| bg.addState(new int[]{-android.R.attr.state_pressed}, gd_background); | |||
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {//16 | |||
| setBackground(bg); | |||
| } else { | |||
| //noinspection deprecation | |||
| setBackgroundDrawable(bg); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,31 +0,0 @@ | |||
| <?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:clipChildren="false" | |||
| android:clipToPadding="false"> | |||
| <TextView | |||
| android:id="@+id/tv_tab_title" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:layout_centerInParent="true" | |||
| android:gravity="center" | |||
| android:singleLine="true"/> | |||
| <com.mindspore.customview.tablayout.widget.MsgView | |||
| android:id="@+id/rtv_msg_tip" | |||
| xmlns:mv="http://schemas.android.com/apk/res-auto" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:gravity="center" | |||
| android:textColor="#ffffff" | |||
| android:textSize="11.5sp" | |||
| android:visibility="gone" | |||
| mv:mv_backgroundColor="#FD481F" | |||
| mv:mv_isRadiusHalfHeight="true" | |||
| mv:mv_strokeColor="#ffffff" | |||
| mv:mv_strokeWidth="1dp"/> | |||
| </RelativeLayout> | |||
| @@ -1,45 +0,0 @@ | |||
| <?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:clipChildren="false" | |||
| android:clipToPadding="false"> | |||
| <LinearLayout | |||
| android:id="@+id/ll_tap" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:layout_centerInParent="true" | |||
| android:gravity="center" | |||
| android:orientation="vertical"> | |||
| <TextView | |||
| android:id="@+id/tv_tab_title" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:singleLine="true"/> | |||
| <ImageView | |||
| android:id="@+id/iv_tab_icon" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content"/> | |||
| </LinearLayout> | |||
| <com.mindspore.customview.tablayout.widget.MsgView | |||
| android:id="@+id/rtv_msg_tip" | |||
| xmlns:mv="http://schemas.android.com/apk/res-auto" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:layout_toRightOf="@+id/ll_tap" | |||
| android:gravity="center" | |||
| android:textColor="#ffffff" | |||
| android:textSize="11.5sp" | |||
| android:visibility="gone" | |||
| mv:mv_backgroundColor="#FD481F" | |||
| mv:mv_isRadiusHalfHeight="true" | |||
| mv:mv_strokeColor="#ffffff" | |||
| mv:mv_strokeWidth="1dp"/> | |||
| </RelativeLayout> | |||
| @@ -1,44 +0,0 @@ | |||
| <?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:clipChildren="false" | |||
| android:clipToPadding="false"> | |||
| <LinearLayout | |||
| android:id="@+id/ll_tap" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:layout_centerInParent="true" | |||
| android:gravity="center" | |||
| android:orientation="horizontal"> | |||
| <ImageView | |||
| android:id="@+id/iv_tab_icon" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content"/> | |||
| <TextView | |||
| android:id="@+id/tv_tab_title" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:singleLine="true"/> | |||
| </LinearLayout> | |||
| <com.mindspore.customview.tablayout.widget.MsgView | |||
| android:layout_toRightOf="@+id/ll_tap" | |||
| android:id="@+id/rtv_msg_tip" | |||
| xmlns:mv="http://schemas.android.com/apk/res-auto" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:gravity="center" | |||
| android:textColor="#ffffff" | |||
| android:textSize="11.5sp" | |||
| android:visibility="gone" | |||
| mv:mv_backgroundColor="#FD481F" | |||
| mv:mv_isRadiusHalfHeight="true" | |||
| mv:mv_strokeColor="#ffffff" | |||
| mv:mv_strokeWidth="1dp"/> | |||
| </RelativeLayout> | |||
| @@ -1,45 +0,0 @@ | |||
| <?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:clipChildren="false" | |||
| android:clipToPadding="false"> | |||
| <LinearLayout | |||
| android:id="@+id/ll_tap" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:layout_centerInParent="true" | |||
| android:gravity="center" | |||
| android:orientation="horizontal"> | |||
| <TextView | |||
| android:id="@+id/tv_tab_title" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:singleLine="true"/> | |||
| <ImageView | |||
| android:id="@+id/iv_tab_icon" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content"/> | |||
| </LinearLayout> | |||
| <com.mindspore.customview.tablayout.widget.MsgView | |||
| android:id="@+id/rtv_msg_tip" | |||
| xmlns:mv="http://schemas.android.com/apk/res-auto" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:layout_toRightOf="@+id/ll_tap" | |||
| android:gravity="center" | |||
| android:textColor="#ffffff" | |||
| android:textSize="11.5sp" | |||
| android:visibility="gone" | |||
| mv:mv_backgroundColor="#FD481F" | |||
| mv:mv_isRadiusHalfHeight="true" | |||
| mv:mv_strokeColor="#ffffff" | |||
| mv:mv_strokeWidth="1dp"/> | |||
| </RelativeLayout> | |||
| @@ -1,39 +0,0 @@ | |||
| <?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:clipChildren="false" | |||
| android:clipToPadding="false"> | |||
| <LinearLayout | |||
| android:id="@+id/ll_tap" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:layout_centerInParent="true" | |||
| android:gravity="center" | |||
| android:orientation="horizontal"> | |||
| <TextView | |||
| android:id="@+id/tv_tab_title" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:singleLine="true"/> | |||
| </LinearLayout> | |||
| <com.mindspore.customview.tablayout.widget.MsgView | |||
| android:layout_toRightOf="@+id/ll_tap" | |||
| android:id="@+id/rtv_msg_tip" | |||
| xmlns:mv="http://schemas.android.com/apk/res-auto" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:gravity="center" | |||
| android:textColor="#ffffff" | |||
| android:textSize="11.5sp" | |||
| android:visibility="gone" | |||
| mv:mv_backgroundColor="#FD481F" | |||
| mv:mv_isRadiusHalfHeight="true" | |||
| mv:mv_strokeColor="#ffffff" | |||
| mv:mv_strokeWidth="1dp"/> | |||
| </RelativeLayout> | |||
| @@ -1,44 +0,0 @@ | |||
| <?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:clipChildren="false" | |||
| android:clipToPadding="false"> | |||
| <LinearLayout | |||
| android:id="@+id/ll_tap" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:layout_centerInParent="true" | |||
| android:gravity="center" | |||
| android:orientation="vertical"> | |||
| <ImageView | |||
| android:id="@+id/iv_tab_icon" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content"/> | |||
| <TextView | |||
| android:id="@+id/tv_tab_title" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:singleLine="true"/> | |||
| </LinearLayout> | |||
| <com.mindspore.customview.tablayout.widget.MsgView | |||
| android:id="@+id/rtv_msg_tip" | |||
| xmlns:mv="http://schemas.android.com/apk/res-auto" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:layout_toRightOf="@+id/ll_tap" | |||
| android:gravity="center" | |||
| android:textColor="#ffffff" | |||
| android:textSize="11.5sp" | |||
| android:visibility="gone" | |||
| mv:mv_backgroundColor="#FD481F" | |||
| mv:mv_isRadiusHalfHeight="true" | |||
| mv:mv_strokeColor="#ffffff" | |||
| mv:mv_strokeWidth="1dp"/> | |||
| </RelativeLayout> | |||
| @@ -1,163 +1,20 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <resources> | |||
| <attr name="tl_divider_color" format="color" /> | |||
| <attr name="tl_divider_padding" format="dimension" /> | |||
| <attr name="tl_divider_width" format="dimension" /> | |||
| <attr name="tl_indicator_anim_duration" format="integer" /> | |||
| <attr name="tl_indicator_anim_enable" format="boolean" /> | |||
| <attr name="tl_indicator_bounce_enable" format="boolean" /> | |||
| <attr name="tl_indicator_color" format="color" /> | |||
| <attr name="tl_indicator_corner_radius" format="dimension" /> | |||
| <attr name="tl_indicator_gravity" format="enum"> | |||
| <enum name="TOP" value="48" /> | |||
| <enum name="BOTTOM" value="80" /> | |||
| </attr> | |||
| <attr name="tl_indicator_height" format="dimension" /> | |||
| <attr name="tl_indicator_margin_bottom" format="dimension" /> | |||
| <attr name="tl_indicator_margin_left" format="dimension" /> | |||
| <attr name="tl_indicator_margin_right" format="dimension" /> | |||
| <attr name="tl_indicator_margin_top" format="dimension" /> | |||
| <attr name="tl_indicator_style" format="enum"> | |||
| <enum name="NORMAL" value="0" /> | |||
| <enum name="TRIANGLE" value="1" /> | |||
| <enum name="BLOCK" value="2" /> | |||
| </attr> | |||
| <attr name="tl_indicator_width" format="dimension" /> | |||
| <attr name="tl_indicator_width_equal_title" format="boolean" /> | |||
| <attr name="tl_tab_padding" format="dimension" /> | |||
| <attr name="tl_tab_space_equal" format="boolean" /> | |||
| <attr name="tl_tab_width" format="dimension" /> | |||
| <attr name="tl_textAllCaps" format="boolean" /> | |||
| <attr name="tl_textBold" format="enum"> | |||
| <enum name="NONE" value="0" /> | |||
| <enum name="SELECT" value="1" /> | |||
| <enum name="BOTH" value="2" /> | |||
| </attr> | |||
| <attr name="tl_textSelectColor" format="color" /> | |||
| <attr name="tl_textUnselectColor" format="color" /> | |||
| <attr name="tl_textsize" format="dimension" /> | |||
| <attr name="tl_underline_color" format="color" /> | |||
| <attr name="tl_underline_gravity" format="enum"> | |||
| <enum name="TOP" value="48" /> | |||
| <enum name="BOTTOM" value="80" /> | |||
| </attr> | |||
| <attr name="tl_underline_height" format="dimension" /> | |||
| <declare-styleable name="CommonTabLayout"> | |||
| <attr name="tl_indicator_color" /> | |||
| <attr name="tl_indicator_height" /> | |||
| <attr name="tl_indicator_width" /> | |||
| <attr name="tl_indicator_margin_left" /> | |||
| <attr name="tl_indicator_margin_top" /> | |||
| <attr name="tl_indicator_margin_right" /> | |||
| <attr name="tl_indicator_margin_bottom" /> | |||
| <attr name="tl_indicator_corner_radius" /> | |||
| <attr name="tl_indicator_gravity" /> | |||
| <attr name="tl_indicator_style" /> | |||
| <attr name="tl_indicator_anim_enable" /> | |||
| <attr name="tl_indicator_anim_duration" /> | |||
| <attr name="tl_indicator_bounce_enable" /> | |||
| <attr name="tl_underline_color" /> | |||
| <attr name="tl_underline_height" /> | |||
| <attr name="tl_underline_gravity" /> | |||
| <attr name="tl_divider_color" /> | |||
| <attr name="tl_divider_width" /> | |||
| <attr name="tl_divider_padding" /> | |||
| <attr name="tl_tab_padding" /> | |||
| <attr name="tl_tab_space_equal" /> | |||
| <attr name="tl_tab_width" /> | |||
| <attr name="tl_textsize" /> | |||
| <attr name="tl_textSelectColor" /> | |||
| <attr name="tl_textUnselectColor" /> | |||
| <attr name="tl_textBold" /> | |||
| <attr name="tl_textAllCaps" /> | |||
| <attr name="tl_iconWidth" format="dimension" /> | |||
| <attr name="tl_iconHeight" format="dimension" /> | |||
| <attr name="tl_iconVisible" format="boolean" /> | |||
| <attr name="tl_iconGravity" format="enum"> | |||
| <enum name="LEFT" value="3" /> | |||
| <enum name="TOP" value="48" /> | |||
| <enum name="RIGHT" value="5" /> | |||
| <enum name="BOTTOM" value="80" /> | |||
| </attr> | |||
| <attr name="tl_iconMargin" format="dimension" /> | |||
| </declare-styleable> | |||
| <declare-styleable name="MsgView"> | |||
| <attr name="mv_backgroundColor" format="color" /> | |||
| <attr name="mv_cornerRadius" format="dimension" /> | |||
| <attr name="mv_strokeWidth" format="dimension" /> | |||
| <attr name="mv_strokeColor" format="color" /> | |||
| <attr name="mv_isRadiusHalfHeight" format="boolean" /> | |||
| <attr name="mv_isWidthHeightEqual" format="boolean" /> | |||
| </declare-styleable> | |||
| <declare-styleable name="SegmentTabLayout"> | |||
| <attr name="tl_indicator_color" /> | |||
| <attr name="tl_indicator_height" /> | |||
| <attr name="tl_indicator_margin_left" /> | |||
| <attr name="tl_indicator_margin_top" /> | |||
| <attr name="tl_indicator_margin_right" /> | |||
| <attr name="tl_indicator_margin_bottom" /> | |||
| <attr name="tl_indicator_corner_radius" /> | |||
| <attr name="tl_indicator_anim_enable" /> | |||
| <attr name="tl_indicator_anim_duration" /> | |||
| <attr name="tl_indicator_bounce_enable" /> | |||
| <attr name="tl_divider_color" /> | |||
| <attr name="tl_divider_width" /> | |||
| <attr name="tl_divider_padding" /> | |||
| <attr name="tl_tab_padding" /> | |||
| <attr name="tl_tab_space_equal" /> | |||
| <attr name="tl_tab_width" /> | |||
| <attr name="tl_textsize" /> | |||
| <attr name="tl_textSelectColor" /> | |||
| <attr name="tl_textUnselectColor" /> | |||
| <attr name="tl_textBold" /> | |||
| <attr name="tl_textAllCaps" /> | |||
| <attr name="tl_bar_color" format="color" /> | |||
| <attr name="tl_bar_stroke_color" format="color" /> | |||
| <attr name="tl_bar_stroke_width" format="dimension" /> | |||
| </declare-styleable> | |||
| <declare-styleable name="SlidingTabLayout"> | |||
| <attr name="tl_indicator_color" /> | |||
| <attr name="tl_indicator_height" /> | |||
| <attr name="tl_indicator_width" /> | |||
| <attr name="tl_indicator_margin_left" /> | |||
| <attr name="tl_indicator_margin_top" /> | |||
| <attr name="tl_indicator_margin_right" /> | |||
| <attr name="tl_indicator_margin_bottom" /> | |||
| <attr name="tl_indicator_corner_radius" /> | |||
| <attr name="tl_indicator_gravity" /> | |||
| <attr name="tl_indicator_style" /> | |||
| <attr name="tl_indicator_width_equal_title" /> | |||
| <attr name="tl_underline_color" /> | |||
| <attr name="tl_underline_height" /> | |||
| <attr name="tl_underline_gravity" /> | |||
| <attr name="tl_divider_color" /> | |||
| <attr name="tl_divider_width" /> | |||
| <attr name="tl_divider_padding" /> | |||
| <attr name="tl_tab_padding" /> | |||
| <attr name="tl_tab_space_equal" /> | |||
| <attr name="tl_tab_width" /> | |||
| <attr name="tl_textsize" /> | |||
| <attr name="tl_textSelectColor" /> | |||
| <attr name="tl_textUnselectColor" /> | |||
| <attr name="tl_textBold" /> | |||
| <attr name="tl_textAllCaps" /> | |||
| </declare-styleable> | |||
| <declare-styleable name="CountDownView"> | |||
| <attr name="cd_circle_radius" format="dimension" /> | |||
| <attr name="cd_arc_width" format="dimension" /> | |||
| <attr name="cd_arc_color" format="color" /> | |||
| <attr name="cd_bg_color" format="color" /> | |||
| <attr name="cd_text_color" format="color" /> | |||
| <attr name="cd_text_size" format="dimension" /> | |||
| <attr name="cd_animator_time" format="integer" /> | |||
| <attr name="cd_animator_time_unit" format="string" /> | |||
| <attr name="cd_retreat_type" format="enum"> | |||
| <declare-styleable name="MSCountDownView"> | |||
| <attr name="ms_cd_circle_radius" format="dimension" /> | |||
| <attr name="ms_cd_arc_width" format="dimension" /> | |||
| <attr name="ms_cd_arc_color" format="color" /> | |||
| <attr name="ms_cd_bg_color" format="color" /> | |||
| <attr name="ms_cd_text_color" format="color" /> | |||
| <attr name="ms_cd_text_size" format="dimension" /> | |||
| <attr name="ms_cd_animator_time" format="integer" /> | |||
| <attr name="ms_cd_animator_time_unit" format="string" /> | |||
| <attr name="ms_cd_retreat_type" format="enum"> | |||
| <enum name="forward" value="1" /> | |||
| <enum name="back" value="2" /> | |||
| </attr> | |||
| <attr name="cd_location" format="enum"> | |||
| <attr name="ms_cd_location" format="enum"> | |||
| <enum name="left" value="1" /> | |||
| <enum name="top" value="2" /> | |||
| <enum name="right" value="3" /> | |||
| @@ -8,27 +8,21 @@ cmake_minimum_required(VERSION 3.4.1) | |||
| set(CMAKE_VERBOSE_MAKEFILE on) | |||
| set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}) | |||
| set(MINDSPORELITE_VERSION mindspore-lite-1.0.1-runtime-arm64-cpu) | |||
| set(MINDSPORELITE_VERSION mindspore-lite-1.1.1-runtime-arm64-cpu) | |||
| # ============== Set MindSpore Dependencies. ============= | |||
| include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp) | |||
| include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/third_party/flatbuffers/include) | |||
| include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}) | |||
| include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/include) | |||
| include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/include/ir/dtype) | |||
| include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/include/schema) | |||
| include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/minddata/include) | |||
| add_library(mindspore-lite SHARED IMPORTED) | |||
| add_library(minddata-lite SHARED IMPORTED) | |||
| add_library(libmindspore-lite-fp16 SHARED IMPORTED) | |||
| set_target_properties(mindspore-lite PROPERTIES IMPORTED_LOCATION | |||
| ${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/lib/libmindspore-lite.so) | |||
| set_target_properties(minddata-lite PROPERTIES IMPORTED_LOCATION | |||
| ${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/minddata/lib/libminddata-lite.so) | |||
| set_target_properties(libmindspore-lite-fp16 PROPERTIES IMPORTED_LOCATION | |||
| ${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/lib/libmindspore-lite-fp16.so) | |||
| # --------------- MindSpore Lite set End. -------------------- | |||
| @@ -74,7 +68,6 @@ target_link_libraries( # Specifies the target library. | |||
| # --- mindspore --- | |||
| minddata-lite | |||
| mindspore-lite | |||
| libmindspore-lite-fp16 | |||
| # --- other dependencies.--- | |||
| -ljnigraphics | |||
| @@ -4,13 +4,13 @@ | |||
| * The libraries can be downloaded manually. | |||
| */ | |||
| def targetMindSporeInclude = "src/main/cpp/" | |||
| def mindsporeLite_Version = "mindspore-lite-1.0.1-runtime-arm64-cpu" | |||
| def mindsporeLite_Version = "mindspore-lite-1.1.1-runtime-arm64-cpu" | |||
| def targetModelFile = "src/main/assets/model/mobilenetv2.ms" | |||
| def mindSporeLibrary_arm64 = "src/main/cpp/${mindsporeLite_Version}.tar.gz" | |||
| def modelDownloadUrl = "https://download.mindspore.cn/model_zoo/official/lite/mobilenetv2_openimage_lite/mobilenetv2.ms" | |||
| def mindsporeLiteDownloadUrl = "https://ms-release.obs.cn-north-4.myhuaweicloud.com/1.0.1/lite/android_aarch64/${mindsporeLite_Version}.tar.gz" | |||
| def mindsporeLiteDownloadUrl = "https://ms-release.obs.cn-north-4.myhuaweicloud.com/1.1.1/MindSpore/lite/release_0220/android/${mindsporeLite_Version}.tar.gz" | |||
| def cleantargetMindSporeInclude = "src/main/cpp" | |||
| @@ -29,7 +29,6 @@ | |||
| #include "MSNetWork.h" | |||
| #include "lite_cv/lite_mat.h" | |||
| #include "lite_cv/image_process.h" | |||
| #include "mindspore-lite-1.0.1-runtime-arm64-cpu/minddata/include/lite_cv/lite_mat.h" | |||
| using mindspore::dataset::LiteMat; | |||
| using mindspore::dataset::LPixelType; | |||
| @@ -1,5 +0,0 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <background android:drawable="@color/ic_launcher_background"/> | |||
| <foreground android:drawable="@mipmap/ic_launcher_foreground"/> | |||
| </adaptive-icon> | |||
| @@ -1,5 +0,0 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <background android:drawable="@color/ic_launcher_background"/> | |||
| <foreground android:drawable="@mipmap/ic_launcher_foreground"/> | |||
| </adaptive-icon> | |||