From: @sishuikang Reviewed-by: @zhanghaibo5,@zhanghaibo5,@hangangqiang Signed-off-by: @zhanghaibo5pull/14624/MERGE
| @@ -15,9 +15,10 @@ | |||||
| */ | */ | ||||
| package com.mindspore.himindspore.bean; | 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 String title; | ||||
| public int selectedIcon; | public int selectedIcon; | ||||
| @@ -30,17 +31,17 @@ public class TabEntity implements CustomTabEntity { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public String getTabTitle() { | |||||
| public String getMSTabTitle() { | |||||
| return title; | return title; | ||||
| } | } | ||||
| @Override | @Override | ||||
| public int getTabSelectedIcon() { | |||||
| public int getMSTabIconChecked() { | |||||
| return selectedIcon; | return selectedIcon; | ||||
| } | } | ||||
| @Override | @Override | ||||
| public int getTabUnselectedIcon() { | |||||
| public int getMSTabIconUnchecked() { | |||||
| return unSelectedIcon; | return unSelectedIcon; | ||||
| } | } | ||||
| } | } | ||||
| @@ -40,7 +40,7 @@ import androidx.appcompat.app.AlertDialog; | |||||
| import com.mindspore.common.sp.Preferences; | import com.mindspore.common.sp.Preferences; | ||||
| import com.mindspore.common.utils.Utils; | 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.R; | ||||
| import com.mindspore.himindspore.base.BaseActivity; | import com.mindspore.himindspore.base.BaseActivity; | ||||
| import com.mindspore.himindspore.ui.main.MainActivity; | import com.mindspore.himindspore.ui.main.MainActivity; | ||||
| @@ -63,7 +63,7 @@ public class SplashActivity extends BaseActivity implements EasyPermissions.Perm | |||||
| private SharedPreferences prefs; | private SharedPreferences prefs; | ||||
| private CountDownView cdvTime; | |||||
| private MSCountDownView cdvTime; | |||||
| private boolean isCheckPrivacy = false; | private boolean isCheckPrivacy = false; | ||||
| private View mContentView; | private View mContentView; | ||||
| @@ -24,22 +24,25 @@ import android.net.Uri; | |||||
| import android.os.Build; | import android.os.Build; | ||||
| import android.os.Environment; | import android.os.Environment; | ||||
| import android.util.Log; | 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 android.widget.Toast; | ||||
| import androidx.core.content.FileProvider; | import androidx.core.content.FileProvider; | ||||
| import androidx.fragment.app.Fragment; | import androidx.fragment.app.Fragment; | ||||
| import androidx.viewpager.widget.ViewPager; | import androidx.viewpager.widget.ViewPager; | ||||
| import com.google.android.material.tabs.TabLayout; | |||||
| import com.mindspore.common.base.adapter.BasePagerAdapter; | import com.mindspore.common.base.adapter.BasePagerAdapter; | ||||
| import com.mindspore.customview.dialog.UpdateDialog; | 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.R; | ||||
| import com.mindspore.himindspore.base.BaseActivity; | import com.mindspore.himindspore.base.BaseActivity; | ||||
| import com.mindspore.himindspore.comment.FragmentFactory; | import com.mindspore.himindspore.comment.FragmentFactory; | ||||
| import com.mindspore.himindspore.net.FileDownLoadObserver; | import com.mindspore.himindspore.net.FileDownLoadObserver; | ||||
| import com.mindspore.himindspore.net.UpdateInfoBean; | import com.mindspore.himindspore.net.UpdateInfoBean; | ||||
| import com.mindspore.himindspore.ui.view.MSTabEntity; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| @@ -49,16 +52,18 @@ public class MainActivity extends BaseActivity<MainPresenter> implements MainCon | |||||
| private static final String TAG = "MainActivity"; | private static final String TAG = "MainActivity"; | ||||
| private ViewPager mVpHome; | private ViewPager mVpHome; | ||||
| private CommonTabLayout mCtlTable; | |||||
| private TabLayout mTabLayout; | |||||
| private int now_version; | private int now_version; | ||||
| private ProgressDialog progressDialog; | private ProgressDialog progressDialog; | ||||
| private List<MSTabEntity> mTabEntities; | |||||
| @Override | @Override | ||||
| protected void init() { | protected void init() { | ||||
| presenter = new MainPresenter(this); | presenter = new MainPresenter(this); | ||||
| mVpHome = findViewById(R.id.vp_home); | mVpHome = findViewById(R.id.vp_home); | ||||
| mCtlTable = findViewById(R.id.ctl_table); | |||||
| mTabLayout = findViewById(R.id.tab_layout); | |||||
| showPackaeInfo(); | showPackaeInfo(); | ||||
| initTabLayout(); | initTabLayout(); | ||||
| initViewPager(); | initViewPager(); | ||||
| @@ -82,19 +87,68 @@ public class MainActivity extends BaseActivity<MainPresenter> implements MainCon | |||||
| } | } | ||||
| private void initTabLayout() { | 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 | @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 | @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() { | private void initViewPager() { | ||||
| @@ -104,23 +158,7 @@ public class MainActivity extends BaseActivity<MainPresenter> implements MainCon | |||||
| fragments.add(FragmentFactory.getInstance().getMeFragment()); | fragments.add(FragmentFactory.getInstance().getMeFragment()); | ||||
| BasePagerAdapter adapter = new BasePagerAdapter(getSupportFragmentManager(), fragments); | BasePagerAdapter adapter = new BasePagerAdapter(getSupportFragmentManager(), fragments); | ||||
| mVpHome.setAdapter(adapter); | 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.setOffscreenPageLimit(3); | ||||
| mVpHome.setCurrentItem(0); | mVpHome.setCurrentItem(0); | ||||
| } | } | ||||
| @@ -171,7 +209,7 @@ public class MainActivity extends BaseActivity<MainPresenter> implements MainCon | |||||
| public void showUpdate(final UpdateInfoBean updateInfo) { | public void showUpdate(final UpdateInfoBean updateInfo) { | ||||
| if (now_version != updateInfo.getVersionCode()) { | 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.setTitleString(getResources().getString(R.string.app_update_lastest) + updateInfo.getVersionName()); | ||||
| updateDialog.setContentString(updateInfo.getMessage()); | updateDialog.setContentString(updateInfo.getMessage()); | ||||
| updateDialog.setYesOnclickListener(() -> downFile()); | updateDialog.setYesOnclickListener(() -> downFile()); | ||||
| @@ -201,12 +239,9 @@ public class MainActivity extends BaseActivity<MainPresenter> implements MainCon | |||||
| @Override | @Override | ||||
| public void onProgress(final int progress, final long total) { | 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; | package com.mindspore.himindspore.ui.main; | ||||
| import com.mindspore.customview.tablayout.listener.CustomTabEntity; | |||||
| import com.mindspore.himindspore.net.FileDownLoadObserver; | import com.mindspore.himindspore.net.FileDownLoadObserver; | ||||
| import com.mindspore.himindspore.net.UpdateInfoBean; | import com.mindspore.himindspore.net.UpdateInfoBean; | ||||
| import com.mindspore.himindspore.ui.view.MSTabEntity; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| public interface MainContract { | public interface MainContract { | ||||
| @@ -31,7 +31,7 @@ public interface MainContract { | |||||
| } | } | ||||
| interface Presenter { | interface Presenter { | ||||
| ArrayList<CustomTabEntity> getTabEntity(); | |||||
| List<MSTabEntity> getTabEntity(); | |||||
| void getUpdateInfo(); | void getUpdateInfo(); | ||||
| @@ -19,13 +19,13 @@ import android.content.res.TypedArray; | |||||
| import android.util.Log; | import android.util.Log; | ||||
| import com.mindspore.common.utils.Utils; | import com.mindspore.common.utils.Utils; | ||||
| import com.mindspore.customview.tablayout.listener.CustomTabEntity; | |||||
| import com.mindspore.himindspore.R; | import com.mindspore.himindspore.R; | ||||
| import com.mindspore.himindspore.base.BasePresenter; | import com.mindspore.himindspore.base.BasePresenter; | ||||
| import com.mindspore.himindspore.bean.TabEntity; | import com.mindspore.himindspore.bean.TabEntity; | ||||
| import com.mindspore.himindspore.net.FileDownLoadObserver; | import com.mindspore.himindspore.net.FileDownLoadObserver; | ||||
| import com.mindspore.himindspore.net.RetrofitHelper; | import com.mindspore.himindspore.net.RetrofitHelper; | ||||
| import com.mindspore.himindspore.net.UpdateInfoBean; | import com.mindspore.himindspore.net.UpdateInfoBean; | ||||
| import com.mindspore.himindspore.ui.view.MSTabEntity; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| @@ -51,15 +51,15 @@ public class MainPresenter extends BasePresenter<MainActivity> implements MainCo | |||||
| @Override | @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 mIconUnSelectIds = Utils.getApp().getResources().obtainTypedArray(R.array.main_tab_un_select); | ||||
| TypedArray mIconSelectIds = Utils.getApp().getResources().obtainTypedArray(R.array.main_tab_select); | TypedArray mIconSelectIds = Utils.getApp().getResources().obtainTypedArray(R.array.main_tab_select); | ||||
| String[] mainTitles = Utils.getApp().getResources().getStringArray(R.array.main_tab_title); | String[] mainTitles = Utils.getApp().getResources().getStringArray(R.array.main_tab_title); | ||||
| for (int i = 0; i < mainTitles.length; i++) { | for (int i = 0; i < mainTitles.length; i++) { | ||||
| int unSelectId = mIconUnSelectIds.getResourceId(i, R.drawable.experience_uncheck); | int unSelectId = mIconUnSelectIds.getResourceId(i, R.drawable.experience_uncheck); | ||||
| int selectId = mIconSelectIds.getResourceId(i, R.drawable.experience_checked); | 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(); | mIconUnSelectIds.recycle(); | ||||
| mIconSelectIds.recycle(); | mIconSelectIds.recycle(); | ||||
| @@ -13,16 +13,16 @@ | |||||
| * See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and | ||||
| * limitations under the License. | * limitations under the License. | ||||
| */ | */ | ||||
| package com.mindspore.customview.tablayout.listener; | |||||
| package com.mindspore.himindspore.ui.view; | |||||
| import androidx.annotation.DrawableRes; | import androidx.annotation.DrawableRes; | ||||
| public interface CustomTabEntity { | |||||
| String getTabTitle(); | |||||
| public interface MSTabEntity { | |||||
| String getMSTabTitle(); | |||||
| @DrawableRes | @DrawableRes | ||||
| int getTabSelectedIcon(); | |||||
| int getMSTabIconChecked(); | |||||
| @DrawableRes | @DrawableRes | ||||
| int getTabUnselectedIcon(); | |||||
| int getMSTabIconUnchecked(); | |||||
| } | } | ||||
| @@ -1,43 +1,36 @@ | |||||
| <?xml version="1.0" encoding="utf-8"?> | <?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" | xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
| android:layout_width="match_parent" | android:layout_width="match_parent" | ||||
| android:layout_height="match_parent" | android:layout_height="match_parent" | ||||
| android:orientation="vertical"> | 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_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 | <View | ||||
| android:id="@+id/lineView" | android:id="@+id/lineView" | ||||
| android:layout_above="@+id/ctl_table" | |||||
| android:layout_width="match_parent" | android:layout_width="match_parent" | ||||
| android:layout_height="1px" | |||||
| android:layout_height="1dp" | |||||
| android:background="@color/divider_gray" /> | 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_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" | android:background="@color/white" | ||||
| tools:context=".ui.guide.SplashActivity"> | tools:context=".ui.guide.SplashActivity"> | ||||
| <ImageView | <ImageView | ||||
| android:id="@+id/image_logo" | android:id="@+id/image_logo" | ||||
| android:layout_width="160dp" | android:layout_width="160dp" | ||||
| @@ -48,23 +47,23 @@ | |||||
| app:layout_constraintTop_toBottomOf="@+id/title" /> | app:layout_constraintTop_toBottomOf="@+id/title" /> | ||||
| <com.mindspore.customview.countdown.CountDownView | |||||
| <com.mindspore.customview.countdown.MSCountDownView | |||||
| android:id="@+id/cdv_time" | android:id="@+id/cdv_time" | ||||
| android:layout_width="wrap_content" | android:layout_width="wrap_content" | ||||
| android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||||
| android:layout_gravity="end" | android:layout_gravity="end" | ||||
| android:layout_marginTop="40dp" | android:layout_marginTop="40dp" | ||||
| android:layout_marginEnd="20dp" | 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_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> | </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"?> | <?xml version="1.0" encoding="utf-8"?> | ||||
| <resources> | <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="forward" value="1" /> | ||||
| <enum name="back" value="2" /> | <enum name="back" value="2" /> | ||||
| </attr> | </attr> | ||||
| <attr name="cd_location" format="enum"> | |||||
| <attr name="ms_cd_location" format="enum"> | |||||
| <enum name="left" value="1" /> | <enum name="left" value="1" /> | ||||
| <enum name="top" value="2" /> | <enum name="top" value="2" /> | ||||
| <enum name="right" value="3" /> | <enum name="right" value="3" /> | ||||
| @@ -8,27 +8,21 @@ cmake_minimum_required(VERSION 3.4.1) | |||||
| set(CMAKE_VERBOSE_MAKEFILE on) | set(CMAKE_VERBOSE_MAKEFILE on) | ||||
| set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}) | 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. ============= | # ============== Set MindSpore Dependencies. ============= | ||||
| include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp) | 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_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/include) | 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) | include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/minddata/include) | ||||
| add_library(mindspore-lite SHARED IMPORTED) | add_library(mindspore-lite SHARED IMPORTED) | ||||
| add_library(minddata-lite SHARED IMPORTED) | add_library(minddata-lite SHARED IMPORTED) | ||||
| add_library(libmindspore-lite-fp16 SHARED IMPORTED) | |||||
| set_target_properties(mindspore-lite PROPERTIES IMPORTED_LOCATION | set_target_properties(mindspore-lite PROPERTIES IMPORTED_LOCATION | ||||
| ${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/lib/libmindspore-lite.so) | ${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/lib/libmindspore-lite.so) | ||||
| set_target_properties(minddata-lite PROPERTIES IMPORTED_LOCATION | set_target_properties(minddata-lite PROPERTIES IMPORTED_LOCATION | ||||
| ${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/minddata/lib/libminddata-lite.so) | ${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. -------------------- | # --------------- MindSpore Lite set End. -------------------- | ||||
| @@ -74,7 +68,6 @@ target_link_libraries( # Specifies the target library. | |||||
| # --- mindspore --- | # --- mindspore --- | ||||
| minddata-lite | minddata-lite | ||||
| mindspore-lite | mindspore-lite | ||||
| libmindspore-lite-fp16 | |||||
| # --- other dependencies.--- | # --- other dependencies.--- | ||||
| -ljnigraphics | -ljnigraphics | ||||
| @@ -4,13 +4,13 @@ | |||||
| * The libraries can be downloaded manually. | * The libraries can be downloaded manually. | ||||
| */ | */ | ||||
| def targetMindSporeInclude = "src/main/cpp/" | 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 targetModelFile = "src/main/assets/model/mobilenetv2.ms" | ||||
| def mindSporeLibrary_arm64 = "src/main/cpp/${mindsporeLite_Version}.tar.gz" | 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 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" | def cleantargetMindSporeInclude = "src/main/cpp" | ||||
| @@ -29,7 +29,6 @@ | |||||
| #include "MSNetWork.h" | #include "MSNetWork.h" | ||||
| #include "lite_cv/lite_mat.h" | #include "lite_cv/lite_mat.h" | ||||
| #include "lite_cv/image_process.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::LiteMat; | ||||
| using mindspore::dataset::LPixelType; | 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> | |||||