diff --git a/FlycoTabLayoutZ_Lib/.gitignore b/FlycoTabLayoutZ_Lib/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/FlycoTabLayoutZ_Lib/.gitignore @@ -0,0 +1 @@ +/build diff --git a/FlycoTabLayoutZ_Lib/build.gradle b/FlycoTabLayoutZ_Lib/build.gradle new file mode 100644 index 0000000..09c8a19 --- /dev/null +++ b/FlycoTabLayoutZ_Lib/build.gradle @@ -0,0 +1,58 @@ +apply plugin: 'com.android.library' +//apply plugin: 'com.novoda.bintray-release' + +version = "1.3.3" +android { + compileSdkVersion 28 + buildToolsVersion "28.0.3" + + defaultConfig { + minSdkVersion 17 + targetSdkVersion 28 + versionCode 5 + versionName version + } + buildTypes { + MT6789Debug {} + MT6789Release {} + Huaruian8768Debug {} + Huaruian8768Release {} + iPlay50SEDebug {} + iPlay50SERelease {} + unisocDebug {} + unisocRelease {} + mtk11Debug {} + mtk11Release {} + teclastMTKDebug {} + teclastMTKRelease {} + G6Debug {} + G6Release {} + G13Debug {} + G13Release {} + Teclast8515Debug {} + Teclast8515Release {} + teclastUnisocdebug {} + teclastUnisocrelease {} + teclastUnisocUserdebug {} + zhanRuiDebug {} + zhanRuiRelease {} + zhanRuiUserdebugReleas {} + debug {} + release {} + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.legacy:legacy-support-v4:1.0.0' +} + +//// jcenter发布的信息 +//publish { +// userOrg = 'lizp' // 创建repo的位置 +// groupId = 'com.lzp' // 引用的分组名称 +// artifactId = 'FlycoTabLayoutZ'//项目名称 +// publishVersion = version//版本号 +// desc = '在FlycoTabLayout的基础上,扩展出SlidingScaleTabLayout,实现滑动可以改变tab字体的大小的切换效果' +// website = 'https://github.com/li504799868/FlycoTabLayoutZ' +//} \ No newline at end of file diff --git a/FlycoTabLayoutZ_Lib/proguard-rules.pro b/FlycoTabLayoutZ_Lib/proguard-rules.pro new file mode 100644 index 0000000..48100e3 --- /dev/null +++ b/FlycoTabLayoutZ_Lib/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/lihui/work/AndroidStudio/sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/FlycoTabLayoutZ_Lib/src/main/AndroidManifest.xml b/FlycoTabLayoutZ_Lib/src/main/AndroidManifest.xml new file mode 100644 index 0000000..e0a940b --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/CommonTabLayout.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/CommonTabLayout.java new file mode 100644 index 0000000..302ec2a --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/CommonTabLayout.java @@ -0,0 +1,986 @@ +package com.flyco.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.flyco.tablayout.listener.CustomTabEntity; +import com.flyco.tablayout.listener.OnTabSelectListener; +import com.flyco.tablayout.utils.FragmentChangeManager; +import com.flyco.tablayout.utils.UnreadMsgUtils; +import com.flyco.tablayout.widget.MsgView; + +import java.util.ArrayList; + +/** + * 没有继承HorizontalScrollView不能滑动,对于ViewPager无依赖 + */ +public class CommonTabLayout extends FrameLayout implements ValueAnimator.AnimatorUpdateListener { + private Context mContext; + private ArrayList mTabEntitys = new ArrayList<>(); + private LinearLayout mTabsContainer; + private int mCurrentTab; + private int mLastTab; + private int mTabCount; + /** + * 用于绘制显示器 + */ + private Rect mIndicatorRect = new Rect(); + private GradientDrawable mIndicatorDrawable = new GradientDrawable(); + + private Paint mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Paint mDividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Paint mTrianglePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Path mTrianglePath = new Path(); + private static final int STYLE_NORMAL = 0; + private static final int STYLE_TRIANGLE = 1; + private static final int STYLE_BLOCK = 2; + private int mIndicatorStyle = STYLE_NORMAL; + + private float mTabPadding; + private boolean mTabSpaceEqual; + private float mTabWidth; + + /** + * indicator + */ + private int mIndicatorColor; + private float mIndicatorHeight; + private float mIndicatorWidth; + private float mIndicatorCornerRadius; + private float mIndicatorMarginLeft; + private float mIndicatorMarginTop; + private float mIndicatorMarginRight; + private float mIndicatorMarginBottom; + private long mIndicatorAnimDuration; + private boolean mIndicatorAnimEnable; + private boolean mIndicatorBounceEnable; + private int mIndicatorGravity; + + /** + * underline + */ + private int mUnderlineColor; + private float mUnderlineHeight; + private int mUnderlineGravity; + + /** + * divider + */ + private int mDividerColor; + private float mDividerWidth; + private float mDividerPadding; + + /** + * title + */ + private static final int TEXT_BOLD_NONE = 0; + private static final int TEXT_BOLD_WHEN_SELECT = 1; + private static final int TEXT_BOLD_BOTH = 2; + private float mTextsize; + private int mTextSelectColor; + private int mTextUnselectColor; + private int mTextBold; + private boolean mTextAllCaps; + + /** + * icon + */ + private boolean mIconVisible; + private int mIconGravity; + private float mIconWidth; + private float mIconHeight; + private float mIconMargin; + + private int mHeight; + + /** + * anim + */ + private ValueAnimator mValueAnimator; + private OvershootInterpolator mInterpolator = new OvershootInterpolator(1.5f); + + private FragmentChangeManager mFragmentChangeManager; + + public CommonTabLayout(Context context) { + this(context, null, 0); + } + + public CommonTabLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CommonTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setWillNotDraw(false);//重写onDraw方法,需要调用这个方法来清除flag + setClipChildren(false); + setClipToPadding(false); + + this.mContext = context; + mTabsContainer = new LinearLayout(context); + addView(mTabsContainer); + + obtainAttributes(context, attrs); + + //get layout_height + String height = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_height"); + + //create ViewPager + if (height.equals(ViewGroup.LayoutParams.MATCH_PARENT + "")) { + } else if (height.equals(ViewGroup.LayoutParams.WRAP_CONTENT + "")) { + } else { + int[] systemAttrs = {android.R.attr.layout_height}; + TypedArray a = context.obtainStyledAttributes(attrs, systemAttrs); + mHeight = a.getDimensionPixelSize(0, ViewGroup.LayoutParams.WRAP_CONTENT); + a.recycle(); + } + + mValueAnimator = ValueAnimator.ofObject(new PointEvaluator(), mLastP, mCurrentP); + mValueAnimator.addUpdateListener(this); + } + + private void obtainAttributes(Context context, AttributeSet attrs) { + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CommonTabLayout); + + mIndicatorStyle = ta.getInt(R.styleable.CommonTabLayout_tl_indicator_style, 0); + mIndicatorColor = ta.getColor(R.styleable.CommonTabLayout_tl_indicator_color, Color.parseColor(mIndicatorStyle == STYLE_BLOCK ? "#4B6A87" : "#ffffff")); + mIndicatorHeight = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_height, + dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 4 : (mIndicatorStyle == STYLE_BLOCK ? -1 : 2))); + mIndicatorWidth = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_width, dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 10 : -1)); + mIndicatorCornerRadius = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_corner_radius, dp2px(mIndicatorStyle == STYLE_BLOCK ? -1 : 0)); + mIndicatorMarginLeft = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_margin_left, dp2px(0)); + mIndicatorMarginTop = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_margin_top, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0)); + mIndicatorMarginRight = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_margin_right, dp2px(0)); + mIndicatorMarginBottom = ta.getDimension(R.styleable.CommonTabLayout_tl_indicator_margin_bottom, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0)); + mIndicatorAnimEnable = ta.getBoolean(R.styleable.CommonTabLayout_tl_indicator_anim_enable, true); + mIndicatorBounceEnable = ta.getBoolean(R.styleable.CommonTabLayout_tl_indicator_bounce_enable, true); + mIndicatorAnimDuration = ta.getInt(R.styleable.CommonTabLayout_tl_indicator_anim_duration, -1); + mIndicatorGravity = ta.getInt(R.styleable.CommonTabLayout_tl_indicator_gravity, Gravity.BOTTOM); + + mUnderlineColor = ta.getColor(R.styleable.CommonTabLayout_tl_underline_color, Color.parseColor("#ffffff")); + mUnderlineHeight = ta.getDimension(R.styleable.CommonTabLayout_tl_underline_height, dp2px(0)); + mUnderlineGravity = ta.getInt(R.styleable.CommonTabLayout_tl_underline_gravity, Gravity.BOTTOM); + + mDividerColor = ta.getColor(R.styleable.CommonTabLayout_tl_divider_color, Color.parseColor("#ffffff")); + mDividerWidth = ta.getDimension(R.styleable.CommonTabLayout_tl_divider_width, dp2px(0)); + mDividerPadding = ta.getDimension(R.styleable.CommonTabLayout_tl_divider_padding, dp2px(12)); + + mTextsize = ta.getDimension(R.styleable.CommonTabLayout_tl_textSize, sp2px(13f)); + mTextSelectColor = ta.getColor(R.styleable.CommonTabLayout_tl_textSelectColor, Color.parseColor("#ffffff")); + mTextUnselectColor = ta.getColor(R.styleable.CommonTabLayout_tl_textUnSelectColor, Color.parseColor("#AAffffff")); + mTextBold = ta.getInt(R.styleable.CommonTabLayout_tl_textBold, TEXT_BOLD_NONE); + mTextAllCaps = ta.getBoolean(R.styleable.CommonTabLayout_tl_textAllCaps, false); + + mIconVisible = ta.getBoolean(R.styleable.CommonTabLayout_tl_iconVisible, true); + mIconGravity = ta.getInt(R.styleable.CommonTabLayout_tl_iconGravity, Gravity.TOP); + mIconWidth = ta.getDimension(R.styleable.CommonTabLayout_tl_iconWidth, dp2px(0)); + mIconHeight = ta.getDimension(R.styleable.CommonTabLayout_tl_iconHeight, dp2px(0)); + mIconMargin = ta.getDimension(R.styleable.CommonTabLayout_tl_iconMargin, dp2px(2.5f)); + + mTabSpaceEqual = ta.getBoolean(R.styleable.CommonTabLayout_tl_tab_space_equal, true); + mTabWidth = ta.getDimension(R.styleable.CommonTabLayout_tl_tab_width, dp2px(-1)); + mTabPadding = ta.getDimension(R.styleable.CommonTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? dp2px(0) : dp2px(10)); + + ta.recycle(); + } + + public void setTabData(ArrayList tabEntitys) { + if (tabEntitys == null || tabEntitys.size() == 0) { + throw new IllegalStateException("TabEntitys can not be NULL or EMPTY !"); + } + + this.mTabEntitys.clear(); + this.mTabEntitys.addAll(tabEntitys); + + notifyDataSetChanged(); + } + + /** + * 关联数据支持同时切换fragments + */ + public void setTabData(ArrayList tabEntitys, FragmentActivity fa, int containerViewId, ArrayList fragments) { + mFragmentChangeManager = new FragmentChangeManager(fa.getSupportFragmentManager(), containerViewId, fragments); + setTabData(tabEntitys); + } + + /** + * 更新数据 + */ + public void notifyDataSetChanged() { + mTabsContainer.removeAllViews(); + this.mTabCount = mTabEntitys.size(); + View tabView; + for (int i = 0; i < mTabCount; i++) { + if (mIconGravity == Gravity.LEFT) { + tabView = View.inflate(mContext, R.layout.layout_tab_left, null); + } else if (mIconGravity == Gravity.RIGHT) { + tabView = View.inflate(mContext, R.layout.layout_tab_right, null); + } else if (mIconGravity == Gravity.BOTTOM) { + tabView = View.inflate(mContext, R.layout.layout_tab_bottom, null); + } else { + tabView = View.inflate(mContext, R.layout.layout_tab_top, null); + } + + tabView.setTag(i); + addTab(i, tabView); + } + + updateTabStyles(); + } + + /** + * 创建并添加tab + */ + private void addTab(final int position, View tabView) { + TextView tv_tab_title = 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(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 = tabView.findViewById(R.id.tv_tab_title); + tv_tab_title.setTextColor(i == mCurrentTab ? mTextSelectColor : mTextUnselectColor); + tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextsize); +// tv_tab_title.setPadding((int) mTabPadding, 0, (int) mTabPadding, 0); + if (mTextAllCaps) { + tv_tab_title.setText(tv_tab_title.getText().toString().toUpperCase()); + } + + if (mTextBold == TEXT_BOLD_BOTH) { + tv_tab_title.getPaint().setFakeBoldText(true); + } + // 被选中设置为粗体 + else if (mTextBold == TEXT_BOLD_WHEN_SELECT && i == mCurrentTab) { + tv_tab_title.getPaint().setFakeBoldText(true); + } else if (mTextBold == TEXT_BOLD_NONE) { + tv_tab_title.getPaint().setFakeBoldText(false); + } + + ImageView iv_tab_icon = 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 = tabView.findViewById(R.id.tv_tab_title); + tab_title.setTextColor(isSelect ? mTextSelectColor : mTextUnselectColor); + ImageView iv_tab_icon = tabView.findViewById(R.id.iv_tab_icon); + CustomTabEntity tabEntity = mTabEntitys.get(i); + iv_tab_icon.setImageResource(isSelect ? tabEntity.getTabSelectedIcon() : tabEntity.getTabUnselectedIcon()); + if (mTextBold == TEXT_BOLD_WHEN_SELECT) { + tab_title.getPaint().setFakeBoldText(isSelect); + } + } + } + + private void calcOffset() { + final View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab); + mCurrentP.left = currentTabView.getLeft(); + mCurrentP.right = currentTabView.getRight(); + + final View lastTabView = mTabsContainer.getChildAt(this.mLastTab); + mLastP.left = lastTabView.getLeft(); + mLastP.right = lastTabView.getRight(); + +// Log.d("AAA", "mLastP--->" + mLastP.left + "&" + mLastP.right); +// Log.d("AAA", "mCurrentP--->" + mCurrentP.left + "&" + mCurrentP.right); + if (mLastP.left == mCurrentP.left && mLastP.right == mCurrentP.right) { + invalidate(); + } else { + mValueAnimator.setObjectValues(mLastP, mCurrentP); + if (mIndicatorBounceEnable) { + mValueAnimator.setInterpolator(mInterpolator); + } + + if (mIndicatorAnimDuration < 0) { + mIndicatorAnimDuration = mIndicatorBounceEnable ? 500 : 250; + } + mValueAnimator.setDuration(mIndicatorAnimDuration); + mValueAnimator.start(); + } + } + + private void calcIndicatorRect() { + View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab); + float left = currentTabView.getLeft(); + float right = currentTabView.getRight(); + + mIndicatorRect.left = (int) left; + mIndicatorRect.right = (int) right; + + if (mIndicatorWidth < 0) { //indicatorWidth小于0时,原jpardogo's PagerSlidingTabStrip + + } else {//indicatorWidth大于0时,圆角矩形以及三角形 + float indicatorLeft = currentTabView.getLeft() + (currentTabView.getWidth() - mIndicatorWidth) / 2; + + mIndicatorRect.left = (int) indicatorLeft; + mIndicatorRect.right = (int) (mIndicatorRect.left + mIndicatorWidth); + } + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab); + IndicatorPoint p = (IndicatorPoint) animation.getAnimatedValue(); + mIndicatorRect.left = (int) p.left; + mIndicatorRect.right = (int) p.right; + + if (mIndicatorWidth < 0) { //indicatorWidth小于0时,原jpardogo's PagerSlidingTabStrip + + } else {//indicatorWidth大于0时,圆角矩形以及三角形 + float indicatorLeft = p.left + (currentTabView.getWidth() - mIndicatorWidth) / 2; + + mIndicatorRect.left = (int) indicatorLeft; + mIndicatorRect.right = (int) (mIndicatorRect.left + mIndicatorWidth); + } + invalidate(); + } + + private boolean mIsFirstDraw = true; + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (isInEditMode() || mTabCount <= 0) { + return; + } + + int height = getHeight(); + int paddingLeft = getPaddingLeft(); + // draw divider + if (mDividerWidth > 0) { + mDividerPaint.setStrokeWidth(mDividerWidth); + mDividerPaint.setColor(mDividerColor); + for (int i = 0; i < mTabCount - 1; i++) { + View tab = mTabsContainer.getChildAt(i); + canvas.drawLine(paddingLeft + tab.getRight(), mDividerPadding, paddingLeft + tab.getRight(), height - mDividerPadding, mDividerPaint); + } + } + + // draw underline + if (mUnderlineHeight > 0) { + mRectPaint.setColor(mUnderlineColor); + if (mUnderlineGravity == Gravity.BOTTOM) { + canvas.drawRect(paddingLeft, height - mUnderlineHeight, mTabsContainer.getWidth() + paddingLeft, height, mRectPaint); + } else { + canvas.drawRect(paddingLeft, 0, mTabsContainer.getWidth() + paddingLeft, mUnderlineHeight, mRectPaint); + } + } + + //draw indicator line + if (mIndicatorAnimEnable) { + if (mIsFirstDraw) { + mIsFirstDraw = false; + calcIndicatorRect(); + } + } else { + calcIndicatorRect(); + } + + + if (mIndicatorStyle == STYLE_TRIANGLE) { + if (mIndicatorHeight > 0) { + mTrianglePaint.setColor(mIndicatorColor); + mTrianglePath.reset(); + mTrianglePath.moveTo(paddingLeft + mIndicatorRect.left, height); + mTrianglePath.lineTo(paddingLeft + mIndicatorRect.left / 2 + mIndicatorRect.right / 2, height - mIndicatorHeight); + mTrianglePath.lineTo(paddingLeft + mIndicatorRect.right, height); + mTrianglePath.close(); + canvas.drawPath(mTrianglePath, mTrianglePaint); + } + } else if (mIndicatorStyle == STYLE_BLOCK) { + if (mIndicatorHeight < 0) { + mIndicatorHeight = height - mIndicatorMarginTop - mIndicatorMarginBottom; + } else { + + } + + if (mIndicatorHeight > 0) { + if (mIndicatorCornerRadius < 0 || mIndicatorCornerRadius > mIndicatorHeight / 2) { + mIndicatorCornerRadius = mIndicatorHeight / 2; + } + + mIndicatorDrawable.setColor(mIndicatorColor); + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + (int) mIndicatorMarginTop, (int) (paddingLeft + mIndicatorRect.right - mIndicatorMarginRight), + (int) (mIndicatorMarginTop + mIndicatorHeight)); + mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius); + mIndicatorDrawable.draw(canvas); + } + } else { + /* mRectPaint.setColor(mIndicatorColor); + calcIndicatorRect(); + canvas.drawRect(getPaddingLeft() + mIndicatorRect.left, getHeight() - mIndicatorHeight, + mIndicatorRect.right + getPaddingLeft(), getHeight(), mRectPaint);*/ + + if (mIndicatorHeight > 0) { + mIndicatorDrawable.setColor(mIndicatorColor); + if (mIndicatorGravity == Gravity.BOTTOM) { + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + height - (int) mIndicatorHeight - (int) mIndicatorMarginBottom, + paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight, + height - (int) mIndicatorMarginBottom); + } else { + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + (int) mIndicatorMarginTop, + paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight, + (int) mIndicatorHeight + (int) mIndicatorMarginTop); + } + mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius); + mIndicatorDrawable.draw(canvas); + } + } + } + + //setter and getter + public void setCurrentTab(int currentTab) { + mLastTab = this.mCurrentTab; + this.mCurrentTab = currentTab; + updateTabSelection(currentTab); + if (mFragmentChangeManager != null) { + mFragmentChangeManager.setFragments(currentTab); + } + if (mIndicatorAnimEnable) { + calcOffset(); + } else { + invalidate(); + } + } + + public void setIndicatorStyle(int indicatorStyle) { + this.mIndicatorStyle = indicatorStyle; + invalidate(); + } + + public void setTabPadding(float tabPadding) { + this.mTabPadding = dp2px(tabPadding); + updateTabStyles(); + } + + public void setTabSpaceEqual(boolean tabSpaceEqual) { + this.mTabSpaceEqual = tabSpaceEqual; + updateTabStyles(); + } + + public void setTabWidth(float tabWidth) { + this.mTabWidth = dp2px(tabWidth); + updateTabStyles(); + } + + public void setIndicatorColor(int indicatorColor) { + this.mIndicatorColor = indicatorColor; + invalidate(); + } + + public void setIndicatorHeight(float indicatorHeight) { + this.mIndicatorHeight = dp2px(indicatorHeight); + invalidate(); + } + + public void setIndicatorWidth(float indicatorWidth) { + this.mIndicatorWidth = dp2px(indicatorWidth); + invalidate(); + } + + public void setIndicatorCornerRadius(float indicatorCornerRadius) { + this.mIndicatorCornerRadius = dp2px(indicatorCornerRadius); + invalidate(); + } + + public void setIndicatorGravity(int indicatorGravity) { + this.mIndicatorGravity = indicatorGravity; + invalidate(); + } + + public void setIndicatorMargin(float indicatorMarginLeft, float indicatorMarginTop, + float indicatorMarginRight, float indicatorMarginBottom) { + this.mIndicatorMarginLeft = dp2px(indicatorMarginLeft); + this.mIndicatorMarginTop = dp2px(indicatorMarginTop); + this.mIndicatorMarginRight = dp2px(indicatorMarginRight); + this.mIndicatorMarginBottom = dp2px(indicatorMarginBottom); + invalidate(); + } + + public void setIndicatorAnimDuration(long indicatorAnimDuration) { + this.mIndicatorAnimDuration = indicatorAnimDuration; + } + + public void setIndicatorAnimEnable(boolean indicatorAnimEnable) { + this.mIndicatorAnimEnable = indicatorAnimEnable; + } + + public void setIndicatorBounceEnable(boolean indicatorBounceEnable) { + this.mIndicatorBounceEnable = indicatorBounceEnable; + } + + public void setUnderlineColor(int underlineColor) { + this.mUnderlineColor = underlineColor; + invalidate(); + } + + public void setUnderlineHeight(float underlineHeight) { + this.mUnderlineHeight = dp2px(underlineHeight); + invalidate(); + } + + public void setUnderlineGravity(int underlineGravity) { + this.mUnderlineGravity = underlineGravity; + invalidate(); + } + + public void setDividerColor(int dividerColor) { + this.mDividerColor = dividerColor; + invalidate(); + } + + public void setDividerWidth(float dividerWidth) { + this.mDividerWidth = dp2px(dividerWidth); + invalidate(); + } + + public void setDividerPadding(float dividerPadding) { + this.mDividerPadding = dp2px(dividerPadding); + invalidate(); + } + + public void setTextsize(float textsize) { + this.mTextsize = sp2px(textsize); + updateTabStyles(); + } + + public void setTextSelectColor(int textSelectColor) { + this.mTextSelectColor = textSelectColor; + updateTabStyles(); + } + + public void setTextUnselectColor(int textUnselectColor) { + this.mTextUnselectColor = textUnselectColor; + updateTabStyles(); + } + + public void setTextBold(int textBold) { + this.mTextBold = textBold; + updateTabStyles(); + } + + public void setIconVisible(boolean iconVisible) { + this.mIconVisible = iconVisible; + updateTabStyles(); + } + + public void setIconGravity(int iconGravity) { + this.mIconGravity = iconGravity; + notifyDataSetChanged(); + } + + public void setIconWidth(float iconWidth) { + this.mIconWidth = dp2px(iconWidth); + updateTabStyles(); + } + + public void setIconHeight(float iconHeight) { + this.mIconHeight = dp2px(iconHeight); + updateTabStyles(); + } + + public void setIconMargin(float iconMargin) { + this.mIconMargin = dp2px(iconMargin); + updateTabStyles(); + } + + public void setTextAllCaps(boolean textAllCaps) { + this.mTextAllCaps = textAllCaps; + updateTabStyles(); + } + + + public int getTabCount() { + return mTabCount; + } + + public int getCurrentTab() { + return mCurrentTab; + } + + public int getIndicatorStyle() { + return mIndicatorStyle; + } + + public float getTabPadding() { + return mTabPadding; + } + + public boolean isTabSpaceEqual() { + return mTabSpaceEqual; + } + + public float getTabWidth() { + return mTabWidth; + } + + public int getIndicatorColor() { + return mIndicatorColor; + } + + public float getIndicatorHeight() { + return mIndicatorHeight; + } + + public float getIndicatorWidth() { + return mIndicatorWidth; + } + + public float getIndicatorCornerRadius() { + return mIndicatorCornerRadius; + } + + public float getIndicatorMarginLeft() { + return mIndicatorMarginLeft; + } + + public float getIndicatorMarginTop() { + return mIndicatorMarginTop; + } + + public float getIndicatorMarginRight() { + return mIndicatorMarginRight; + } + + public float getIndicatorMarginBottom() { + return mIndicatorMarginBottom; + } + + public long getIndicatorAnimDuration() { + return mIndicatorAnimDuration; + } + + public boolean isIndicatorAnimEnable() { + return mIndicatorAnimEnable; + } + + public boolean isIndicatorBounceEnable() { + return mIndicatorBounceEnable; + } + + public int getUnderlineColor() { + return mUnderlineColor; + } + + public float getUnderlineHeight() { + return mUnderlineHeight; + } + + public int getDividerColor() { + return mDividerColor; + } + + public float getDividerWidth() { + return mDividerWidth; + } + + public float getDividerPadding() { + return mDividerPadding; + } + + public float getTextsize() { + return mTextsize; + } + + public int getTextSelectColor() { + return mTextSelectColor; + } + + public int getTextUnselectColor() { + return mTextUnselectColor; + } + + public int getTextBold() { + return mTextBold; + } + + public boolean isTextAllCaps() { + return mTextAllCaps; + } + + public int getIconGravity() { + return mIconGravity; + } + + public float getIconWidth() { + return mIconWidth; + } + + public float getIconHeight() { + return mIconHeight; + } + + public float getIconMargin() { + return mIconMargin; + } + + public boolean isIconVisible() { + return mIconVisible; + } + + + public ImageView getIconView(int tab) { + View tabView = mTabsContainer.getChildAt(tab); + ImageView iv_tab_icon = 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 = 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 mInitSetMap = new SparseArray<>(); + + /** + * 显示未读消息 + * + * @param position 显示tab位置 + * @param num num小于等于0显示红点,num大于0显示数字 + */ + public void showMsg(int position, int num) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + UnreadMsgUtils.show(tipView, num); + + if (mInitSetMap.get(position) != null && mInitSetMap.get(position)) { + return; + } + + if (!mIconVisible) { + setMsgMargin(position, 2, 2); + } else { + setMsgMargin(position, 0, + mIconGravity == Gravity.LEFT || mIconGravity == Gravity.RIGHT ? 4 : 0); + } + + mInitSetMap.put(position, true); + } + } + + /** + * 显示未读红点 + * + * @param position 显示tab位置 + */ + public void showDot(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + showMsg(position, 0); + } + + public void hideMsg(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + tipView.setVisibility(View.GONE); + } + } + + /** + * 设置提示红点偏移,注意 + * 1.控件为固定高度:参照点为tab内容的右上角 + * 2.控件高度不固定(WRAP_CONTENT):参照点为tab内容的右上角,此时高度已是红点的最高显示范围,所以这时bottomPadding其实就是topPadding + */ + public void setMsgMargin(int position, float leftPadding, float bottomPadding) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + TextView tv_tab_title = tabView.findViewById(R.id.tv_tab_title); + mTextPaint.setTextSize(mTextsize); + float textWidth = mTextPaint.measureText(tv_tab_title.getText().toString()); + float textHeight = mTextPaint.descent() - mTextPaint.ascent(); + MarginLayoutParams lp = (MarginLayoutParams) tipView.getLayoutParams(); + + float iconH = mIconHeight; + float margin = 0; + if (mIconVisible) { + if (iconH <= 0) { + iconH = mContext.getResources().getDrawable(mTabEntitys.get(position).getTabSelectedIcon()).getIntrinsicHeight(); + } + margin = mIconMargin; + } + + if (mIconGravity == Gravity.TOP || mIconGravity == Gravity.BOTTOM) { + lp.leftMargin = dp2px(leftPadding); + lp.topMargin = mHeight > 0 ? (int) (mHeight - textHeight - iconH - margin) / 2 - dp2px(bottomPadding) : dp2px(bottomPadding); + } else { + lp.leftMargin = dp2px(leftPadding); + lp.topMargin = mHeight > 0 ? (int) (mHeight - Math.max(textHeight, iconH)) / 2 - dp2px(bottomPadding) : dp2px(bottomPadding); + } + + tipView.setLayoutParams(lp); + } + } + + /** + * 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 + */ + public MsgView getMsgView(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = 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 { + @Override + public IndicatorPoint evaluate(float fraction, IndicatorPoint startValue, IndicatorPoint endValue) { + float left = startValue.left + fraction * (endValue.left - startValue.left); + float right = startValue.right + fraction * (endValue.right - startValue.right); + IndicatorPoint point = new IndicatorPoint(); + point.left = left; + point.right = right; + return point; + } + } + + + protected int dp2px(float dp) { + final float scale = mContext.getResources().getDisplayMetrics().density; + return (int) (dp * scale + 0.5f); + } + + protected int sp2px(float sp) { + final float scale = this.mContext.getResources().getDisplayMetrics().scaledDensity; + return (int) (sp * scale + 0.5f); + } + +} diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java new file mode 100644 index 0000000..314e20b --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java @@ -0,0 +1,776 @@ +package com.flyco.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.flyco.tablayout.listener.OnTabSelectListener; +import com.flyco.tablayout.utils.FragmentChangeManager; +import com.flyco.tablayout.utils.UnreadMsgUtils; +import com.flyco.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, dp2px(0)); + mIndicatorMarginTop = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_margin_top, 0); + mIndicatorMarginRight = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_margin_right, dp2px(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(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, dp2px(1)); + mDividerPadding = ta.getDimension(R.styleable.SegmentTabLayout_tl_divider_padding, 0); + + mTextsize = ta.getDimension(R.styleable.SegmentTabLayout_tl_textSize, sp2px(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, dp2px(-1)); + mTabPadding = ta.getDimension(R.styleable.SegmentTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? dp2px(0) : dp2px(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, dp2px(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(); + } + + /** + * 关联数据支持同时切换fragments + */ + public void setTabData(String[] titles, FragmentActivity fa, int containerViewId, ArrayList 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(); + } + + /** + * 创建并添加tab + */ + private void addTab(final int position, View tabView) { + TextView tv_tab_title = 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 = tabView.findViewById(R.id.tv_tab_title); + tv_tab_title.setTextColor(i == mCurrentTab ? mTextSelectColor : mTextUnselectColor); + tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextsize); +// tv_tab_title.setPadding((int) mTabPadding, 0, (int) mTabPadding, 0); + if (mTextAllCaps) { + tv_tab_title.setText(tv_tab_title.getText().toString().toUpperCase()); + } + + if (mTextBold == TEXT_BOLD_BOTH) { + tv_tab_title.getPaint().setFakeBoldText(true); + } + // 被选中设置为粗体 + else if (mTextBold == TEXT_BOLD_WHEN_SELECT && i == mCurrentTab) { + 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 = 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(); + +// Log.d("AAA", "mLastP--->" + mLastP.left + "&" + mLastP.right); +// Log.d("AAA", "mCurrentP--->" + mCurrentP.left + "&" + mCurrentP.right); + if (mLastP.left == mCurrentP.left && mLastP.right == mCurrentP.right) { + invalidate(); + } else { + mValueAnimator.setObjectValues(mLastP, mCurrentP); + if (mIndicatorBounceEnable) { + mValueAnimator.setInterpolator(mInterpolator); + } + + if (mIndicatorAnimDuration < 0) { + mIndicatorAnimDuration = mIndicatorBounceEnable ? 500 : 250; + } + mValueAnimator.setDuration(mIndicatorAnimDuration); + mValueAnimator.start(); + } + } + + private void calcIndicatorRect() { + View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab); + float left = currentTabView.getLeft(); + float right = currentTabView.getRight(); + + mIndicatorRect.left = (int) left; + mIndicatorRect.right = (int) right; + + if (!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 = dp2px(tabPadding); + updateTabStyles(); + } + + public void setTabSpaceEqual(boolean tabSpaceEqual) { + this.mTabSpaceEqual = tabSpaceEqual; + updateTabStyles(); + } + + public void setTabWidth(float tabWidth) { + this.mTabWidth = dp2px(tabWidth); + updateTabStyles(); + } + + public void setIndicatorColor(int indicatorColor) { + this.mIndicatorColor = indicatorColor; + invalidate(); + } + + public void setIndicatorHeight(float indicatorHeight) { + this.mIndicatorHeight = dp2px(indicatorHeight); + invalidate(); + } + + public void setIndicatorCornerRadius(float indicatorCornerRadius) { + this.mIndicatorCornerRadius = dp2px(indicatorCornerRadius); + invalidate(); + } + + public void setIndicatorMargin(float indicatorMarginLeft, float indicatorMarginTop, + float indicatorMarginRight, float indicatorMarginBottom) { + this.mIndicatorMarginLeft = dp2px(indicatorMarginLeft); + this.mIndicatorMarginTop = dp2px(indicatorMarginTop); + this.mIndicatorMarginRight = dp2px(indicatorMarginRight); + this.mIndicatorMarginBottom = dp2px(indicatorMarginBottom); + invalidate(); + } + + public void setIndicatorAnimDuration(long indicatorAnimDuration) { + this.mIndicatorAnimDuration = indicatorAnimDuration; + } + + public void setIndicatorAnimEnable(boolean indicatorAnimEnable) { + this.mIndicatorAnimEnable = indicatorAnimEnable; + } + + public void setIndicatorBounceEnable(boolean indicatorBounceEnable) { + this.mIndicatorBounceEnable = indicatorBounceEnable; + } + + public void setDividerColor(int dividerColor) { + this.mDividerColor = dividerColor; + invalidate(); + } + + public void setDividerWidth(float dividerWidth) { + this.mDividerWidth = dp2px(dividerWidth); + invalidate(); + } + + public void setDividerPadding(float dividerPadding) { + this.mDividerPadding = dp2px(dividerPadding); + invalidate(); + } + + public void setTextsize(float textsize) { + this.mTextsize = sp2px(textsize); + updateTabStyles(); + } + + public void setTextSelectColor(int textSelectColor) { + this.mTextSelectColor = textSelectColor; + updateTabStyles(); + } + + public void setTextUnselectColor(int textUnselectColor) { + this.mTextUnselectColor = textUnselectColor; + updateTabStyles(); + } + + public void setTextBold(int textBold) { + this.mTextBold = textBold; + updateTabStyles(); + } + + public void setTextAllCaps(boolean textAllCaps) { + this.mTextAllCaps = textAllCaps; + updateTabStyles(); + } + + public 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 = 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 mInitSetMap = new SparseArray<>(); + + /** + * 显示未读消息 + * + * @param position 显示tab位置 + * @param num num小于等于0显示红点,num大于0显示数字 + */ + public void showMsg(int position, int num) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = 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); + } + } + + /** + * 显示未读红点 + * + * @param position 显示tab位置 + */ + public void showDot(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + showMsg(position, 0); + } + + public void hideMsg(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + tipView.setVisibility(View.GONE); + } + } + + /** + * 设置提示红点偏移,注意 + * 1.控件为固定高度:参照点为tab内容的右上角 + * 2.控件高度不固定(WRAP_CONTENT):参照点为tab内容的右上角,此时高度已是红点的最高显示范围,所以这时bottomPadding其实就是topPadding + */ + public void setMsgMargin(int position, float leftPadding, float bottomPadding) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + TextView tv_tab_title = 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 = dp2px(leftPadding); + lp.topMargin = mHeight > 0 ? (int) (mHeight - textHeight) / 2 - dp2px(bottomPadding) : dp2px(bottomPadding); + + tipView.setLayoutParams(lp); + } + } + + /** + * 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 + */ + public MsgView getMsgView(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = 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 { + @Override + public IndicatorPoint evaluate(float fraction, IndicatorPoint startValue, IndicatorPoint endValue) { + float left = startValue.left + fraction * (endValue.left - startValue.left); + float right = startValue.right + fraction * (endValue.right - startValue.right); + IndicatorPoint point = new IndicatorPoint(); + point.left = left; + point.right = right; + return point; + } + } + + protected int dp2px(float dp) { + final float scale = mContext.getResources().getDisplayMetrics().density; + return (int) (dp * scale + 0.5f); + } + + protected int sp2px(float sp) { + final float scale = this.mContext.getResources().getDisplayMetrics().scaledDensity; + return (int) (sp * scale + 0.5f); + } +} diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/SlidingScaleTabLayout.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/SlidingScaleTabLayout.java new file mode 100644 index 0000000..069b132 --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/SlidingScaleTabLayout.java @@ -0,0 +1,1216 @@ +package com.flyco.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.text.TextUtils; +import android.util.AttributeSet; +import android.util.SparseBooleanArray; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.HorizontalScrollView; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.flyco.tablayout.listener.OnTabSelectListener; +import com.flyco.tablayout.transformer.ExtendTransformer; +import com.flyco.tablayout.transformer.ITabScaleTransformer; +import com.flyco.tablayout.transformer.IViewPagerTransformer; +import com.flyco.tablayout.transformer.TabScaleTransformer; +import com.flyco.tablayout.utils.UnreadMsgUtils; +import com.flyco.tablayout.utils.ViewUtils; +import com.flyco.tablayout.widget.MsgView; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * 滑动切换TabLayout,tab的文字大小会发生变化 + */ +public class SlidingScaleTabLayout extends HorizontalScrollView implements ViewPager.OnPageChangeListener { + + private static final int TOP = 0; + private static final int BOTTOM = 1; + private static final int CENTER = 2; + private static final int LEFT = 0; + private static final int RIGHT = 1; + + private Context mContext; + private ViewPager mViewPager; + private ArrayList 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 mTextSelectSize; + private float mTextUnSelectSize; + private int mTextSelectColor; + private int mTextUnSelectColor; + private int mTextBold; + private boolean mTextAllCaps; + + private int mLastScrollX; + private int mHeight; + private boolean mSnapOnTabClick; + + /** + * tab的上下间距 + */ + private int mTabMarginTop; + private int mTabMarginBottom; + + private int mTabMsgMarginTop; + private int mTabMsgMarginRight; + private int mTabDotMarginTop; + private int mTabDotMarginRight; + private int mTabBackgroundId; + + private boolean openDmg = true; + + /** + * tab中的内容的位置 + */ + private int mTabHorizontalGravity; + + private int mTabVerticalGravity; + + private ITabScaleTransformer iTabScaleTransformer; + + private ExtendTransformer extendTransformer; + + public SlidingScaleTabLayout(Context context) { + this(context, null, 0); + } + + public SlidingScaleTabLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingScaleTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setFillViewport(true);//设置滚动视图是否可以伸缩其内容以填充视口 + setWillNotDraw(false);//重写onDraw方法,需要调用这个方法来清除flag + setClipChildren(false); + setClipToPadding(false); + + this.mContext = context; + mTabsContainer = new LinearLayout(context); + addView(mTabsContainer); + + obtainAttributes(context, attrs); + + //get layout_height + String height = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_height"); + + if (height.equals(ViewGroup.LayoutParams.MATCH_PARENT + "")) { + } else if (height.equals(ViewGroup.LayoutParams.WRAP_CONTENT + "")) { + } else { + int[] systemAttrs = {android.R.attr.layout_height}; + TypedArray a = context.obtainStyledAttributes(attrs, systemAttrs); + mHeight = a.getDimensionPixelSize(0, ViewGroup.LayoutParams.WRAP_CONTENT); + a.recycle(); + } + } + + private void obtainAttributes(Context context, AttributeSet attrs) { + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingScaleTabLayout); + + mIndicatorStyle = ta.getInt(R.styleable.SlidingScaleTabLayout_tl_indicator_style, STYLE_NORMAL); + mIndicatorColor = ta.getColor(R.styleable.SlidingScaleTabLayout_tl_indicator_color, Color.parseColor(mIndicatorStyle == STYLE_BLOCK ? "#4B6A87" : "#ffffff")); + mIndicatorHeight = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_indicator_height, + dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 4 : (mIndicatorStyle == STYLE_BLOCK ? -1 : 2))); + mIndicatorWidth = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_indicator_width, dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 10 : -1)); + mIndicatorCornerRadius = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_indicator_corner_radius, dp2px(mIndicatorStyle == STYLE_BLOCK ? -1 : 0)); + mIndicatorMarginLeft = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_indicator_margin_left, dp2px(0)); + mIndicatorMarginTop = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_indicator_margin_top, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0)); + mIndicatorMarginRight = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_indicator_margin_right, dp2px(0)); + mIndicatorMarginBottom = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_indicator_margin_bottom, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0)); + mIndicatorGravity = ta.getInt(R.styleable.SlidingScaleTabLayout_tl_indicator_gravity, Gravity.BOTTOM); + mIndicatorWidthEqualTitle = ta.getBoolean(R.styleable.SlidingScaleTabLayout_tl_indicator_width_equal_title, false); + + mUnderlineColor = ta.getColor(R.styleable.SlidingScaleTabLayout_tl_underline_color, Color.parseColor("#ffffff")); + mUnderlineHeight = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_underline_height, dp2px(0)); + mUnderlineGravity = ta.getInt(R.styleable.SlidingScaleTabLayout_tl_underline_gravity, Gravity.BOTTOM); + + mDividerColor = ta.getColor(R.styleable.SlidingScaleTabLayout_tl_divider_color, Color.parseColor("#ffffff")); + mDividerWidth = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_divider_width, dp2px(0)); + mDividerPadding = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_divider_padding, dp2px(12)); + + mTextUnSelectSize = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_textUnSelectSize, sp2px(14)); + // 被选中的文字大小,默认额未选中的大小一样 + mTextSelectSize = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_textSelectSize, mTextUnSelectSize); + + mTextSelectColor = ta.getColor(R.styleable.SlidingScaleTabLayout_tl_textSelectColor, Color.parseColor("#ffffff")); + mTextUnSelectColor = ta.getColor(R.styleable.SlidingScaleTabLayout_tl_textUnSelectColor, Color.parseColor("#AAffffff")); + mTextBold = ta.getInt(R.styleable.SlidingScaleTabLayout_tl_textBold, TEXT_BOLD_NONE); + mTextAllCaps = ta.getBoolean(R.styleable.SlidingScaleTabLayout_tl_textAllCaps, false); + + mTabSpaceEqual = ta.getBoolean(R.styleable.SlidingScaleTabLayout_tl_tab_space_equal, false); + mTabWidth = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_tab_width, dp2px(-1)); + mTabPadding = ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? dp2px(0) : dp2px(20)); + // 得到设置的上下间距和gravity + mTabMarginTop = ta.getDimensionPixelSize(R.styleable.SlidingScaleTabLayout_tl_tab_marginTop, 0); + mTabMarginBottom = ta.getDimensionPixelSize(R.styleable.SlidingScaleTabLayout_tl_tab_marginBottom, 0); + + mTabHorizontalGravity = ta.getInt(R.styleable.SlidingScaleTabLayout_tl_tab_horizontal_gravity, CENTER); + mTabVerticalGravity = ta.getInt(R.styleable.SlidingScaleTabLayout_tl_tab_vertical_gravity, CENTER); + + mTabMsgMarginTop = (int) ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_tab_msg_marginTop, 0f); + mTabMsgMarginRight = (int) ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_tab_msg_marginRight, 0f); + + mTabDotMarginTop = (int) ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_tab_dot_marginTop, 0f); + mTabDotMarginRight = (int) ta.getDimension(R.styleable.SlidingScaleTabLayout_tl_tab_dot_marginRight, 0f); + mTabBackgroundId = ta.getResourceId(R.styleable.SlidingScaleTabLayout_tl_tab_background, 0); + openDmg = ta.getBoolean(R.styleable.SlidingScaleTabLayout_tl_openTextDmg, false); + ta.recycle(); + + iTabScaleTransformer = new TabScaleTransformer(this, mTextSelectSize, mTextUnSelectSize, openDmg); + } + + /** + * 关联ViewPager + */ + public void setViewPager(ViewPager vp) { + if (vp == null || vp.getAdapter() == null) { + throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !"); + } + + this.mViewPager = vp; + + initViewPagerListener(); + } + + /** + * 设置标题,不关联ViewPager + */ + public void setTitle(String[] titles) { + mTitles = new ArrayList<>(); + Collections.addAll(mTitles, titles); + initViewPagerListener(); + } + + + /** + * 关联ViewPager,用于不想在ViewPager适配器中设置titles数据的情况 + */ + public void setViewPager(ViewPager vp, String[] titles) { + if (vp == null || vp.getAdapter() == null) { + throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !"); + } + + if (titles == null || titles.length == 0) { + throw new IllegalStateException("Titles can not be EMPTY !"); + } + + if (titles.length != vp.getAdapter().getCount()) { + throw new IllegalStateException("Titles length must be the same as the page count !"); + } + + this.mViewPager = vp; + mTitles = new ArrayList<>(); + Collections.addAll(mTitles, titles); + + initViewPagerListener(); + } + + /** + * 关联ViewPager,用于连适配器都不想自己实例化的情况 + */ + public void setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList 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)); + initViewPagerListener(); + } + + private void initViewPagerListener() { + if (this.mViewPager != null) { + this.mViewPager.removeOnPageChangeListener(this); + this.mViewPager.addOnPageChangeListener(this); + initTransformer(); + } + notifyDataSetChanged(); + } + + private void initTransformer() { + // 如果选中状态的文字大小和未选中状态的文字大小是不同的,开启缩放 + if (mTextUnSelectSize != mTextSelectSize) { + extendTransformer = new ExtendTransformer(); + this.mViewPager.setPageTransformer(true, extendTransformer); + } + } + + /** + * 更新数据 + */ + public void notifyDataSetChanged() { + mTabsContainer.removeAllViews(); + this.mTabCount = mTitles == null ? mViewPager.getAdapter().getCount() : mTitles.size(); + View tabView; + for (int i = 0; i < mTabCount; i++) { + tabView = LayoutInflater.from(mContext).inflate(R.layout.layout_scale_tab, mTabsContainer, false); + TextView title = tabView.findViewById(R.id.tv_tab_title); + // 设置tab的位置信息 + setTabLayoutParams(title); + CharSequence pageTitle = mTitles == null ? mViewPager.getAdapter().getPageTitle(i) : mTitles.get(i); + addTab(i, pageTitle.toString(), tabView); + } + + updateTabStyles(); + } + + private void setTabLayoutParams(TextView title) { + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) title.getLayoutParams(); + params.topMargin = mTabMarginTop; + params.bottomMargin = mTabMarginBottom; + + if (mTabVerticalGravity == TOP) { + params.addRule(RelativeLayout.ALIGN_PARENT_TOP); + } else if (mTabVerticalGravity == BOTTOM) { + params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + } else { + params.addRule(RelativeLayout.CENTER_VERTICAL); + } + + if (mTabHorizontalGravity == LEFT) { + params.addRule(RelativeLayout.ALIGN_PARENT_LEFT); + } else if (mTabHorizontalGravity == RIGHT) { + params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + } else { + params.addRule(RelativeLayout.CENTER_HORIZONTAL); + } + + + title.setLayoutParams(params); + + if (isDmgOpen()) { + ImageView imageView = (ImageView) ViewUtils.findBrotherView(title, R.id.tv_tab_title_dmg, 3); + if (imageView == null) return; + params = (RelativeLayout.LayoutParams) imageView.getLayoutParams(); + params.topMargin = mTabMarginTop; + params.bottomMargin = mTabMarginBottom; + // 调整镜像的问题 + if (mTabVerticalGravity == TOP) { + params.addRule(RelativeLayout.ALIGN_PARENT_TOP); + imageView.setScaleType(ImageView.ScaleType.FIT_START); + } else if (mTabVerticalGravity == BOTTOM) { + params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + imageView.setScaleType(ImageView.ScaleType.FIT_END); + } else { + params.addRule(RelativeLayout.CENTER_VERTICAL); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + } + + if (mTabHorizontalGravity == LEFT) { + params.addRule(RelativeLayout.ALIGN_PARENT_LEFT); + } else if (mTabHorizontalGravity == RIGHT) { + params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + } else { + params.addRule(RelativeLayout.CENTER_HORIZONTAL); + } + + imageView.setLayoutParams(params); + } + + } + + /** + * 如果文字的大小没有变化,不需要开启镜像,请注意 + */ + private boolean isDmgOpen() { + return openDmg && mTextSelectSize != mTextUnSelectSize; + } + + /** + * 创建并添加tab + */ + private void addTab(final int position, String title, View tabView) { + TextView tv_tab_title = tabView.findViewById(R.id.tv_tab_title); + if (tv_tab_title != null) { +// tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, position == mCurrentTab ? mTextSelectSize : mTextUnSelectSize); + tv_tab_title.setText(title); + // 设置tab背景 + if (mTabBackgroundId != 0) { + tv_tab_title.setBackgroundResource(mTabBackgroundId); + } +// if (TextUtils.isEmpty(title)) { +// tabView.setVisibility(View.GONE); +// } else { +// tabView.setVisibility(View.VISIBLE); +// } + } + + tabView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + int position = mTabsContainer.indexOfChild(v); + if (position != -1) { + setCurrentTab(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 v = mTabsContainer.getChildAt(i); +// v.setPadding((int) mTabPadding, v.getPaddingTop(), (int) mTabPadding, v.getPaddingBottom()); + TextView tv_tab_title = v.findViewById(R.id.tv_tab_title); + if (tv_tab_title != null) { + v.setPadding((int) mTabPadding, 0, (int) mTabPadding, 0); + tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, i == mCurrentTab ? mTextSelectSize : mTextUnSelectSize); + tv_tab_title.setTextColor(i == mCurrentTab ? mTextSelectColor : mTextUnSelectColor); + // 设置选中状态 + tv_tab_title.setSelected(i == mCurrentTab); + + 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_WHEN_SELECT) { + tv_tab_title.getPaint().setFakeBoldText(i == mCurrentTab); + } else if (mTextBold == TEXT_BOLD_NONE) { + tv_tab_title.getPaint().setFakeBoldText(false); + } + + if (isDmgOpen()) { + generateTitleDmg(v, tv_tab_title, i); + } + } + } + + } + + private void generateTitleDmg(View tabView, TextView textView, int position) { + // 空字符串不能做镜像,否则会引发空指针 + if (TextUtils.isEmpty(textView.getText())) { + return; + } + + // 如果需要开启镜像,需要把所有的字设置为选中的字体 +// textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextUnSelectSize); +// ImageView imageView = tabView.findViewById(R.id.tv_tab_title_dmg); +// imageView.setImageBitmap(ViewUtils.generateViewCacheBitmap(textView)); +// imageView.setMaxWidth(imageView.getDrawable().getIntrinsicWidth()); + + + ImageView imageView = tabView.findViewById(R.id.tv_tab_title_dmg); + // 如果需要开启镜像,需要把所有的字设置为选中的字体 + if (mTextSelectSize >= mTextUnSelectSize) { + textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSelectSize); + imageView.setImageBitmap(ViewUtils.generateViewCacheBitmap(textView)); + int drawableWidth = imageView.getDrawable().getIntrinsicWidth(); + imageView.setMinimumWidth((int) (drawableWidth * mTextUnSelectSize / mTextSelectSize)); + imageView.setMaxWidth(drawableWidth); + } else { + textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextUnSelectSize); + imageView.setImageBitmap(ViewUtils.generateViewCacheBitmap(textView)); + int drawableWidth = imageView.getDrawable().getIntrinsicWidth(); + imageView.setMinimumWidth((int) (drawableWidth * mTextSelectSize / mTextUnSelectSize)); + imageView.setMaxWidth(drawableWidth); + } + +// iTabScaleTransformer.setNormalWidth(position, imageView.getDrawable().getIntrinsicWidth(), position == mViewPager.getCurrentItem()); + textView.setVisibility(View.GONE); + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + /** + * position:当前View的位置 + * mCurrentPositionOffset:当前View的偏移量比例.[0,1) + */ + this.mCurrentTab = position; + this.mCurrentPositionOffset = positionOffset; + iTabScaleTransformer.onPageScrolled(position, positionOffset, positionOffsetPixels); + scrollToCurrentTab(); + invalidate(); +// Log.i("onPageScrolled", "mCurrentTab:" + mCurrentTab + " positionOffset:" + positionOffset); + if (this.mCurrentPositionOffset == 0) { + updateTabSelection(mCurrentTab); + } + } + + @Override + public void onPageSelected(int position) { + + } + + @Override + public void onPageScrollStateChanged(int state) { +// if (state == ViewPager.SCROLL_STATE_IDLE) { +// updateTabSelection(mCurrentTab); +// } + } + + /** + * HorizontalScrollView滚到当前tab,并且居中显示 + */ + private void scrollToCurrentTab() { + if (mTabCount <= 0) { + return; + } + + int offset = (int) (mCurrentPositionOffset * mTabsContainer.getChildAt(mCurrentTab).getWidth()); + /**当前Tab的left+当前Tab的Width乘以positionOffset*/ + int newScrollX = mTabsContainer.getChildAt(mCurrentTab).getLeft() + offset; + + if (mCurrentTab > 0 || offset > 0) { + /**HorizontalScrollView移动到当前tab,并居中*/ + newScrollX -= getWidth() / 2 - getPaddingLeft(); + calcIndicatorRect(); + newScrollX += ((mTabRect.right - mTabRect.left) / 2); + } + + if (newScrollX != mLastScrollX) { + mLastScrollX = newScrollX; + /** scrollTo(int x,int y):x,y代表的不是坐标点,而是偏移量 + * x:表示离起始位置的x水平方向的偏移量 + * y:表示离起始位置的y垂直方向的偏移量 + */ + scrollTo(newScrollX, 0); + } + } + + private void updateTabSelection(int position) { + for (int i = 0; i < mTabCount; ++i) { + View tabView = mTabsContainer.getChildAt(i); + final boolean isSelect = i == position; + final TextView tab_title = tabView.findViewById(R.id.tv_tab_title); + + if (tab_title != null) { + tab_title.setTextColor(isSelect ? mTextSelectColor : mTextUnSelectColor); + // 设置选中状态 + tab_title.setSelected(isSelect); + + if (mTextBold == TEXT_BOLD_BOTH) { + tab_title.getPaint().setFakeBoldText(true); + } + // 被选中设置为粗体 + else if (mTextBold == TEXT_BOLD_WHEN_SELECT && i == position) { + tab_title.getPaint().setFakeBoldText(true); + } else { + tab_title.getPaint().setFakeBoldText(false); + } + if (isDmgOpen() && (mTextSelectColor != mTextUnSelectColor || mTextBold == TEXT_BOLD_WHEN_SELECT)) { + tab_title.setVisibility(View.VISIBLE); + generateTitleDmg(tabView, tab_title, i); + } else { + final int finalI = i; + tab_title.post(new Runnable() { + @Override + public void run() { + tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, finalI == mCurrentTab ? mTextSelectSize : mTextUnSelectSize); + tab_title.requestLayout(); + } + }); + } + } + } + } + + 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 = currentTabView.findViewById(R.id.tv_tab_title); + 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 = nextTabView.findViewById(R.id.tv_tab_title); + float nextTextWidth = mTextPaint.measureText(next_tab_title.getText().toString()); + float nextMargin = (nextTabRight - nextTabLeft - nextTextWidth) / 2; + margin = margin + mCurrentPositionOffset * (nextMargin - margin); + } + } + + mIndicatorRect.left = (int) left; + mIndicatorRect.right = (int) right; + //for mIndicatorWidthEqualTitle + if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) { + mIndicatorRect.left = (int) (left + margin - 1); + mIndicatorRect.right = (int) (right - margin - 1); + } + + mTabRect.left = (int) left; + mTabRect.right = (int) right; + + if (mIndicatorWidth < 0) { //indicatorWidth小于0时,原jpardogo's PagerSlidingTabStrip + + } else {//indicatorWidth大于0时,圆角矩形以及三角形 + float indicatorLeft = currentTabView.getLeft() + (currentTabView.getWidth() - mIndicatorWidth) / 2; + + if (this.mCurrentTab < mTabCount - 1) { + View nextTab = mTabsContainer.getChildAt(this.mCurrentTab + 1); + indicatorLeft = indicatorLeft + mCurrentPositionOffset * (currentTabView.getWidth() / 2 + nextTab.getWidth() / 2); + } + + mIndicatorRect.left = (int) indicatorLeft; + mIndicatorRect.right = (int) (mIndicatorRect.left + mIndicatorWidth); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (isInEditMode() || mTabCount <= 0) { + return; + } + + int height = getHeight(); + int paddingLeft = getPaddingLeft(); + // draw divider + if (mDividerWidth > 0) { + mDividerPaint.setStrokeWidth(mDividerWidth); + mDividerPaint.setColor(mDividerColor); + for (int i = 0; i < mTabCount - 1; i++) { + View tab = mTabsContainer.getChildAt(i); + canvas.drawLine(paddingLeft + tab.getRight(), mDividerPadding, paddingLeft + tab.getRight(), height - mDividerPadding, mDividerPaint); + } + } + + // draw underline + if (mUnderlineHeight > 0) { + mRectPaint.setColor(mUnderlineColor); + if (mUnderlineGravity == Gravity.BOTTOM) { + canvas.drawRect(paddingLeft, height - mUnderlineHeight, mTabsContainer.getWidth() + paddingLeft, height, mRectPaint); + } else { + canvas.drawRect(paddingLeft, 0, mTabsContainer.getWidth() + paddingLeft, mUnderlineHeight, mRectPaint); + } + } + + //draw indicator line + + calcIndicatorRect(); + if (mIndicatorStyle == STYLE_TRIANGLE) { + if (mIndicatorHeight > 0) { + mTrianglePaint.setColor(mIndicatorColor); + mTrianglePath.reset(); + mTrianglePath.moveTo(paddingLeft + mIndicatorRect.left, height); + mTrianglePath.lineTo(paddingLeft + mIndicatorRect.left / 2 + mIndicatorRect.right / 2, height - mIndicatorHeight); + mTrianglePath.lineTo(paddingLeft + mIndicatorRect.right, height); + mTrianglePath.close(); + canvas.drawPath(mTrianglePath, mTrianglePaint); + } + } else if (mIndicatorStyle == STYLE_BLOCK) { + if (mIndicatorHeight < 0) { + mIndicatorHeight = height - mIndicatorMarginTop - mIndicatorMarginBottom; + } else { + + } + + if (mIndicatorHeight > 0) { + if (mIndicatorCornerRadius < 0 || mIndicatorCornerRadius > mIndicatorHeight / 2) { + mIndicatorCornerRadius = mIndicatorHeight / 2; + } + + mIndicatorDrawable.setColor(mIndicatorColor); + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + (int) mIndicatorMarginTop, (int) (paddingLeft + mIndicatorRect.right - mIndicatorMarginRight), + (int) (mIndicatorMarginTop + mIndicatorHeight)); + mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius); + mIndicatorDrawable.draw(canvas); + } + } else { + /* mRectPaint.setColor(mIndicatorColor); + calcIndicatorRect(); + canvas.drawRect(getPaddingLeft() + mIndicatorRect.left, getHeight() - mIndicatorHeight, + mIndicatorRect.right + getPaddingLeft(), getHeight(), mRectPaint);*/ + + if (mIndicatorHeight > 0) { + mIndicatorDrawable.setColor(mIndicatorColor); + + if (mIndicatorGravity == Gravity.BOTTOM) { + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + height - (int) mIndicatorHeight - (int) mIndicatorMarginBottom, + paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight, + height - (int) mIndicatorMarginBottom); + } else { + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + (int) mIndicatorMarginTop, + paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight, + (int) mIndicatorHeight + (int) mIndicatorMarginTop); + } + mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius); + mIndicatorDrawable.draw(canvas); + } + } + } + + //setter and getter + public void setCurrentTab(int currentTab) { + setCurrentTab(currentTab, !mSnapOnTabClick); + } + + public void setCurrentTab(int currentTab, boolean smoothScroll) { + if (mCurrentTab != currentTab) { + this.mCurrentTab = currentTab; + if (mViewPager != null) { + mViewPager.setCurrentItem(currentTab, smoothScroll); + } + + if (mListener != null) { + mListener.onTabSelect(currentTab); + } + } else { + if (mListener != null) { + mListener.onTabReselect(currentTab); + } + } + } + + public void setIndicatorStyle(int indicatorStyle) { + this.mIndicatorStyle = indicatorStyle; + invalidate(); + } + + public void setTabPadding(float tabPadding) { + this.mTabPadding = dp2px(tabPadding); + updateTabStyles(); + } + + public void setTabSpaceEqual(boolean tabSpaceEqual) { + this.mTabSpaceEqual = tabSpaceEqual; + updateTabStyles(); + } + + public void setTabWidth(float tabWidth) { + this.mTabWidth = dp2px(tabWidth); + updateTabStyles(); + } + + public void setIndicatorColor(int indicatorColor) { + this.mIndicatorColor = indicatorColor; + invalidate(); + } + + public void setIndicatorHeight(float indicatorHeight) { + this.mIndicatorHeight = dp2px(indicatorHeight); + invalidate(); + } + + public void setIndicatorWidth(float indicatorWidth) { + this.mIndicatorWidth = dp2px(indicatorWidth); + invalidate(); + } + + public void setIndicatorCornerRadius(float indicatorCornerRadius) { + this.mIndicatorCornerRadius = dp2px(indicatorCornerRadius); + invalidate(); + } + + public void setIndicatorGravity(int indicatorGravity) { + this.mIndicatorGravity = indicatorGravity; + invalidate(); + } + + public void setIndicatorMargin(float indicatorMarginLeft, float indicatorMarginTop, + float indicatorMarginRight, float indicatorMarginBottom) { + this.mIndicatorMarginLeft = dp2px(indicatorMarginLeft); + this.mIndicatorMarginTop = dp2px(indicatorMarginTop); + this.mIndicatorMarginRight = dp2px(indicatorMarginRight); + this.mIndicatorMarginBottom = dp2px(indicatorMarginBottom); + invalidate(); + } + + public void setIndicatorWidthEqualTitle(boolean indicatorWidthEqualTitle) { + this.mIndicatorWidthEqualTitle = indicatorWidthEqualTitle; + invalidate(); + } + + public void setUnderlineColor(int underlineColor) { + this.mUnderlineColor = underlineColor; + invalidate(); + } + + public void setUnderlineHeight(float underlineHeight) { + this.mUnderlineHeight = dp2px(underlineHeight); + invalidate(); + } + + public void setUnderlineGravity(int underlineGravity) { + this.mUnderlineGravity = underlineGravity; + invalidate(); + } + + public void setDividerColor(int dividerColor) { + this.mDividerColor = dividerColor; + invalidate(); + } + + public void setDividerWidth(float dividerWidth) { + this.mDividerWidth = dp2px(dividerWidth); + invalidate(); + } + + public void setDividerPadding(float dividerPadding) { + this.mDividerPadding = dp2px(dividerPadding); + invalidate(); + } + + public void setTextSelectsize(float textsize) { + this.mTextSelectSize = sp2px(textsize); + initTransformer(); + updateTabStyles(); + } + + public void setTextUnselectSize(int textSize) { + this.mTextUnSelectSize = textSize; + initTransformer(); + 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 getTextSelectSize() { + return mTextSelectSize; + } + + public float getTextUnselectSize() { + return mTextUnSelectSize; + } + + public int getTextSelectColor() { + return mTextSelectColor; + } + + public int getTextUnselectColor() { + return mTextUnSelectColor; + } + + public int getTextBold() { + return mTextBold; + } + + public boolean isTextAllCaps() { + return mTextAllCaps; + } + + public void addViewPagerTransformer(IViewPagerTransformer transformer) { + this.extendTransformer.addViewPagerTransformer(transformer); + } + + public void removeViewPagerTransformer(IViewPagerTransformer transformer) { + this.extendTransformer.removeViewPagerTransformer(transformer); + } + + public List getTransformers() { + return extendTransformer.getTransformers(); + } + + public void setTransformers(List transformers) { + this.extendTransformer.setTransformers(transformers); + } + + public TextView getTitleView(int tab) { + View tabView = mTabsContainer.getChildAt(tab); + return (TextView) tabView.findViewById(R.id.tv_tab_title); + } + + //setter and getter + + // show MsgTipView + private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private SparseBooleanArray mInitSetMap = new SparseBooleanArray(); + + /** + * 显示未读消息 + * + * @param position 显示tab位置 + * @param num num小于等于0显示红点,num大于0显示数字 + */ + public void showMsg(int position, int num) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + UnreadMsgUtils.show(tipView, num); + + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) tipView.getLayoutParams(); + if (openDmg) { + params.addRule(RelativeLayout.ALIGN_END, R.id.tv_tab_title_dmg); + params.addRule(RelativeLayout.ALIGN_TOP, R.id.tv_tab_title_dmg); + } else { + params.addRule(RelativeLayout.ALIGN_END, R.id.tv_tab_title); + params.addRule(RelativeLayout.ALIGN_TOP, R.id.tv_tab_title); + } + + // 红点的位置 + if (num <= 0) { + params.topMargin = mTabDotMarginTop; + params.rightMargin = mTabDotMarginRight; + } + // 未读数的位置 + else { + params.topMargin = mTabMsgMarginTop; + params.rightMargin = mTabMsgMarginRight; + } + + tipView.setLayoutParams(params); + if (mInitSetMap.get(position)) { + return; + } + mInitSetMap.put(position, true); + } + } + + /** + * 显示未读红点 + * + * @param position 显示tab位置 + */ + public void showDot(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + showMsg(position, 0); + } + + /** + * 隐藏未读消息 + */ + public void hideMsg(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + tipView.setVisibility(View.GONE); + } + } + + /** + * 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 + */ + public MsgView getMsgView(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + View tabView = mTabsContainer.getChildAt(position); + return (MsgView) tabView.findViewById(R.id.rtv_msg_tip); + } + + /** + * 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 + */ + public TextView getTitle(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + View tabView = mTabsContainer.getChildAt(position); + if (tabView == null) { + return null; + } + return (TextView) tabView.findViewById(R.id.tv_tab_title); + } + + public ImageView getDmgView(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + View tabView = mTabsContainer.getChildAt(position); + if (tabView == null) { + return null; + } + +// if (tabView.getVisibility() != View.GONE) { +// return null; +// } + + return (ImageView) tabView.findViewById(R.id.tv_tab_title_dmg); + } + + private OnTabSelectListener mListener; + + public void setOnTabSelectListener(OnTabSelectListener listener) { + this.mListener = listener; + } + + class InnerPagerAdapter extends FragmentPagerAdapter { + private ArrayList fragments; + private String[] titles; + + public InnerPagerAdapter(FragmentManager fm, ArrayList 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(@NonNull ViewGroup container, int position, @NonNull Object object) { + // 覆写destroyItem并且空实现,这样每个Fragment中的视图就不会被销毁 + // super.destroyItem(container, position, object); + } + + @Override + public int getItemPosition(@NonNull Object object) { + return PagerAdapter.POSITION_NONE; + } + } + + @Override + protected Parcelable onSaveInstanceState() { + Bundle bundle = new Bundle(); + bundle.putParcelable("instanceState", super.onSaveInstanceState()); + bundle.putInt("mCurrentTab", mCurrentTab); + return bundle; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state instanceof Bundle) { + Bundle bundle = (Bundle) state; + mCurrentTab = bundle.getInt("mCurrentTab"); + state = bundle.getParcelable("instanceState"); + if (mCurrentTab != 0 && mTabsContainer.getChildCount() > 0) { + updateTabSelection(mCurrentTab); + scrollToCurrentTab(); + } + } + super.onRestoreInstanceState(state); + } + + protected int dp2px(float dp) { + final float scale = mContext.getResources().getDisplayMetrics().density; + return (int) (dp * scale + 0.5f); + } + + protected int sp2px(float sp) { + final float scale = this.mContext.getResources().getDisplayMetrics().scaledDensity; + return (int) (sp * scale + 0.5f); + } +} diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/SlidingTabLayout.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/SlidingTabLayout.java new file mode 100644 index 0000000..42752a1 --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/SlidingTabLayout.java @@ -0,0 +1,1012 @@ +package com.flyco.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.SparseBooleanArray; +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.RelativeLayout; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.flyco.tablayout.listener.OnTabSelectListener; +import com.flyco.tablayout.utils.UnreadMsgUtils; +import com.flyco.tablayout.widget.MsgView; + +import java.util.ArrayList; +import java.util.Collections; + +/** + * 滑动TabLayout,对于ViewPager的依赖性强 + */ +public class SlidingTabLayout extends HorizontalScrollView implements ViewPager.OnPageChangeListener { + + private static final int TOP = 0; + private static final int BOTTOM = 1; + private static final int CENTER = 2; + + private Context mContext; + private ViewPager mViewPager; + private ArrayList 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 mTextSelectSize; + private float mTextUnSelectSize; + private int mTextSelectColor; + private int mTextUnSelectColor; + private int mTextBold; + private boolean mTextAllCaps; + + private int mLastScrollX; + private int mHeight; + private boolean mSnapOnTabClick; + + /** + * tab的上下间距 + */ + private int mTabMarginTop; + private int mTabMarginBottom; + + /** + * tab摆放的位置,目前只支持top和bottom + */ + private int mTabGravity; + + public SlidingTabLayout(Context context) { + this(context, null, 0); + } + + public SlidingTabLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setFillViewport(true);//设置滚动视图是否可以伸缩其内容以填充视口 + setWillNotDraw(false);//重写onDraw方法,需要调用这个方法来清除flag + setClipChildren(false); + setClipToPadding(false); + + this.mContext = context; + mTabsContainer = new LinearLayout(context); + addView(mTabsContainer); + + obtainAttributes(context, attrs); + + //get layout_height + String height = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_height"); + + if (height.equals(ViewGroup.LayoutParams.MATCH_PARENT + "")) { + } else if (height.equals(ViewGroup.LayoutParams.WRAP_CONTENT + "")) { + } else { + int[] systemAttrs = {android.R.attr.layout_height}; + TypedArray a = context.obtainStyledAttributes(attrs, systemAttrs); + mHeight = a.getDimensionPixelSize(0, ViewGroup.LayoutParams.WRAP_CONTENT); + a.recycle(); + } + } + + private void obtainAttributes(Context context, AttributeSet attrs) { + TypedArray ta = context.obtainStyledAttributes(attrs, 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, + dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 4 : (mIndicatorStyle == STYLE_BLOCK ? -1 : 2))); + mIndicatorWidth = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_width, dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 10 : -1)); + mIndicatorCornerRadius = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_corner_radius, dp2px(mIndicatorStyle == STYLE_BLOCK ? -1 : 0)); + mIndicatorMarginLeft = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_left, dp2px(0)); + mIndicatorMarginTop = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_top, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0)); + mIndicatorMarginRight = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_right, dp2px(0)); + mIndicatorMarginBottom = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_bottom, dp2px(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, dp2px(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, dp2px(0)); + mDividerPadding = ta.getDimension(R.styleable.SlidingTabLayout_tl_divider_padding, dp2px(12)); + + mTextSelectSize = ta.getDimension(R.styleable.SlidingTabLayout_tl_textSelectSize, sp2px(14)); + mTextUnSelectSize = ta.getDimension(R.styleable.SlidingTabLayout_tl_textUnSelectSize, sp2px(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, dp2px(-1)); + mTabPadding = ta.getDimension(R.styleable.SlidingTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? dp2px(0) : dp2px(20)); + // 得到设置的上下间距和gravity + mTabMarginTop = ta.getDimensionPixelSize(R.styleable.SlidingTabLayout_tl_tab_marginTop, 0); + mTabMarginBottom = ta.getDimensionPixelSize(R.styleable.SlidingTabLayout_tl_tab_marginBottom, 0); + mTabGravity = ta.getInt(R.styleable.SlidingTabLayout_tl_tab_gravity, CENTER); + + ta.recycle(); + } + + /** + * 关联ViewPager + */ + public void setViewPager(ViewPager vp) { + if (vp == null || vp.getAdapter() == null) { + throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !"); + } + + this.mViewPager = vp; + + this.mViewPager.removeOnPageChangeListener(this); + this.mViewPager.addOnPageChangeListener(this); + notifyDataSetChanged(); + } + + /** + * 关联ViewPager,用于不想在ViewPager适配器中设置titles数据的情况 + */ + public void setTitle(String[] titles) { + if (titles == null || titles.length == 0) { + throw new IllegalStateException("Titles can not be EMPTY !"); + } + + mTitles = new ArrayList<>(); + Collections.addAll(mTitles, titles); + notifyDataSetChanged(); + } + + /** + * 关联ViewPager,用于不想在ViewPager适配器中设置titles数据的情况 + */ + public void setViewPager(ViewPager vp, String[] titles) { + if (vp == null || vp.getAdapter() == null) { + throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !"); + } + + if (titles == null || titles.length == 0) { + throw new IllegalStateException("Titles can not be EMPTY !"); + } + + if (titles.length != vp.getAdapter().getCount()) { + throw new IllegalStateException("Titles length must be the same as the page count !"); + } + + this.mViewPager = vp; + mTitles = new ArrayList<>(); + Collections.addAll(mTitles, titles); + + this.mViewPager.removeOnPageChangeListener(this); + this.mViewPager.addOnPageChangeListener(this); + notifyDataSetChanged(); + } + + /** + * 关联ViewPager,用于连适配器都不想自己实例化的情况 + */ + public void setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList 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); + TextView title = tabView.findViewById(R.id.tv_tab_title); + // 设置tab的位置信息 + setTabLayoutParams(title); + CharSequence pageTitle = mTitles == null ? mViewPager.getAdapter().getPageTitle(i) : mTitles.get(i); + addTab(i, pageTitle.toString(), tabView); + } + + updateTabStyles(); + } + + private void setTabLayoutParams(TextView title) { + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) title.getLayoutParams(); + params.topMargin = mTabMarginTop; + params.bottomMargin = mTabMarginBottom; + if (mTabGravity == TOP) { + params.addRule(RelativeLayout.ALIGN_PARENT_TOP); + } else if (mTabGravity == BOTTOM) { + params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + } else { + params.addRule(RelativeLayout.CENTER_VERTICAL); + } + title.setLayoutParams(params); + } + + 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(); + } + + /** + * 创建并添加tab + */ + private void addTab(final int position, String title, View tabView) { + TextView tv_tab_title = 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) { + setCurrentTab(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 v = mTabsContainer.getChildAt(i); +// v.setPadding((int) mTabPadding, v.getPaddingTop(), (int) mTabPadding, v.getPaddingBottom()); + TextView tv_tab_title = 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, i == mCurrentTab ? mTextSelectSize : mTextUnSelectSize); + 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_WHEN_SELECT && i == mCurrentTab) { + tv_tab_title.getPaint().setFakeBoldText(true); + } else if (mTextBold == TEXT_BOLD_NONE) { + tv_tab_title.getPaint().setFakeBoldText(false); + } + } + } + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + /** + * position:当前View的位置 + * mCurrentPositionOffset:当前View的偏移量比例.[0,1) + */ + this.mCurrentTab = position; + this.mCurrentPositionOffset = positionOffset; + scrollToCurrentTab(); + invalidate(); + } + + @Override + public void onPageSelected(int position) { + updateTabSelection(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + } + + /** + * HorizontalScrollView滚到当前tab,并且居中显示 + */ + private void scrollToCurrentTab() { + if (mTabCount <= 0) { + return; + } + + int offset = (int) (mCurrentPositionOffset * mTabsContainer.getChildAt(mCurrentTab).getWidth()); + /**当前Tab的left+当前Tab的Width乘以positionOffset*/ + int newScrollX = mTabsContainer.getChildAt(mCurrentTab).getLeft() + offset; + + if (mCurrentTab > 0 || offset > 0) { + /**HorizontalScrollView移动到当前tab,并居中*/ + newScrollX -= getWidth() / 2 - getPaddingLeft(); + calcIndicatorRect(); + newScrollX += ((mTabRect.right - mTabRect.left) / 2); + } + + if (newScrollX != mLastScrollX) { + mLastScrollX = newScrollX; + /** scrollTo(int x,int y):x,y代表的不是坐标点,而是偏移量 + * x:表示离起始位置的x水平方向的偏移量 + * y:表示离起始位置的y垂直方向的偏移量 + */ + scrollTo(newScrollX, 0); + } + } + + private void updateTabSelection(int position) { + for (int i = 0; i < mTabCount; ++i) { + View tabView = mTabsContainer.getChildAt(i); + final boolean isSelect = i == position; + TextView tab_title = tabView.findViewById(R.id.tv_tab_title); + + if (tab_title != null) { + tab_title.setTextColor(isSelect ? mTextSelectColor : mTextUnSelectColor); + tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, isSelect ? mTextSelectSize : mTextUnSelectSize); + 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 = currentTabView.findViewById(R.id.tv_tab_title); + mTextPaint.setTextSize(mTextSelectSize); + 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 = nextTabView.findViewById(R.id.tv_tab_title); + mTextPaint.setTextSize(mTextUnSelectSize); + float nextTextWidth = mTextPaint.measureText(next_tab_title.getText().toString()); + float nextMargin = (nextTabRight - nextTabLeft - nextTextWidth) / 2; + margin = margin + mCurrentPositionOffset * (nextMargin - margin); + } + } + + mIndicatorRect.left = (int) left; + mIndicatorRect.right = (int) right; + //for mIndicatorWidthEqualTitle + if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) { + mIndicatorRect.left = (int) (left + margin - 1); + mIndicatorRect.right = (int) (right - margin - 1); + } + + mTabRect.left = (int) left; + mTabRect.right = (int) right; + + if (mIndicatorWidth < 0) { //indicatorWidth小于0时,原jpardogo's PagerSlidingTabStrip + + } else {//indicatorWidth大于0时,圆角矩形以及三角形 + float indicatorLeft = currentTabView.getLeft() + (currentTabView.getWidth() - mIndicatorWidth) / 2; + + if (this.mCurrentTab < mTabCount - 1) { + View nextTab = mTabsContainer.getChildAt(this.mCurrentTab + 1); + indicatorLeft = indicatorLeft + mCurrentPositionOffset * (currentTabView.getWidth() / 2 + nextTab.getWidth() / 2); + } + + mIndicatorRect.left = (int) indicatorLeft; + mIndicatorRect.right = (int) (mIndicatorRect.left + mIndicatorWidth); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (isInEditMode() || mTabCount <= 0) { + return; + } + + int height = getHeight(); + int paddingLeft = getPaddingLeft(); + // draw divider + if (mDividerWidth > 0) { + mDividerPaint.setStrokeWidth(mDividerWidth); + mDividerPaint.setColor(mDividerColor); + for (int i = 0; i < mTabCount - 1; i++) { + View tab = mTabsContainer.getChildAt(i); + canvas.drawLine(paddingLeft + tab.getRight(), mDividerPadding, paddingLeft + tab.getRight(), height - mDividerPadding, mDividerPaint); + } + } + + // draw underline + if (mUnderlineHeight > 0) { + mRectPaint.setColor(mUnderlineColor); + if (mUnderlineGravity == Gravity.BOTTOM) { + canvas.drawRect(paddingLeft, height - mUnderlineHeight, mTabsContainer.getWidth() + paddingLeft, height, mRectPaint); + } else { + canvas.drawRect(paddingLeft, 0, mTabsContainer.getWidth() + paddingLeft, mUnderlineHeight, mRectPaint); + } + } + + //draw indicator line + + calcIndicatorRect(); + if (mIndicatorStyle == STYLE_TRIANGLE) { + if (mIndicatorHeight > 0) { + mTrianglePaint.setColor(mIndicatorColor); + mTrianglePath.reset(); + mTrianglePath.moveTo(paddingLeft + mIndicatorRect.left, height); + mTrianglePath.lineTo(paddingLeft + mIndicatorRect.left / 2 + mIndicatorRect.right / 2, height - mIndicatorHeight); + mTrianglePath.lineTo(paddingLeft + mIndicatorRect.right, height); + mTrianglePath.close(); + canvas.drawPath(mTrianglePath, mTrianglePaint); + } + } else if (mIndicatorStyle == STYLE_BLOCK) { + if (mIndicatorHeight < 0) { + mIndicatorHeight = height - mIndicatorMarginTop - mIndicatorMarginBottom; + } else { + + } + + if (mIndicatorHeight > 0) { + if (mIndicatorCornerRadius < 0 || mIndicatorCornerRadius > mIndicatorHeight / 2) { + mIndicatorCornerRadius = mIndicatorHeight / 2; + } + + mIndicatorDrawable.setColor(mIndicatorColor); + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + (int) mIndicatorMarginTop, (int) (paddingLeft + mIndicatorRect.right - mIndicatorMarginRight), + (int) (mIndicatorMarginTop + mIndicatorHeight)); + mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius); + mIndicatorDrawable.draw(canvas); + } + } else { + /* mRectPaint.setColor(mIndicatorColor); + calcIndicatorRect(); + canvas.drawRect(getPaddingLeft() + mIndicatorRect.left, getHeight() - mIndicatorHeight, + mIndicatorRect.right + getPaddingLeft(), getHeight(), mRectPaint);*/ + + if (mIndicatorHeight > 0) { + mIndicatorDrawable.setColor(mIndicatorColor); + + if (mIndicatorGravity == Gravity.BOTTOM) { + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + height - (int) mIndicatorHeight - (int) mIndicatorMarginBottom, + paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight, + height - (int) mIndicatorMarginBottom); + } else { + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + (int) mIndicatorMarginTop, + paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight, + (int) mIndicatorHeight + (int) mIndicatorMarginTop); + } + mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius); + mIndicatorDrawable.draw(canvas); + } + } + } + + //setter and getter + public void setCurrentTab(int currentTab) { + setCurrentTab(currentTab, !mSnapOnTabClick); + } + + public void setCurrentTab(int currentTab, boolean smoothScroll) { + if (mCurrentTab != currentTab) { + this.mCurrentTab = currentTab; + if (mViewPager != null) { + mViewPager.setCurrentItem(currentTab, smoothScroll); + } + + if (mListener != null) { + mListener.onTabSelect(currentTab); + } + } else { + if (mListener != null) { + mListener.onTabReselect(currentTab); + } + } + } + + public void setIndicatorStyle(int indicatorStyle) { + this.mIndicatorStyle = indicatorStyle; + invalidate(); + } + + public void setTabPadding(float tabPadding) { + this.mTabPadding = dp2px(tabPadding); + updateTabStyles(); + } + + public void setTabSpaceEqual(boolean tabSpaceEqual) { + this.mTabSpaceEqual = tabSpaceEqual; + updateTabStyles(); + } + + public void setTabWidth(float tabWidth) { + this.mTabWidth = dp2px(tabWidth); + updateTabStyles(); + } + + public void setIndicatorColor(int indicatorColor) { + this.mIndicatorColor = indicatorColor; + invalidate(); + } + + public void setIndicatorHeight(float indicatorHeight) { + this.mIndicatorHeight = dp2px(indicatorHeight); + invalidate(); + } + + public void setIndicatorWidth(float indicatorWidth) { + this.mIndicatorWidth = dp2px(indicatorWidth); + invalidate(); + } + + public void setIndicatorCornerRadius(float indicatorCornerRadius) { + this.mIndicatorCornerRadius = dp2px(indicatorCornerRadius); + invalidate(); + } + + public void setIndicatorGravity(int indicatorGravity) { + this.mIndicatorGravity = indicatorGravity; + invalidate(); + } + + public void setIndicatorMargin(float indicatorMarginLeft, float indicatorMarginTop, + float indicatorMarginRight, float indicatorMarginBottom) { + this.mIndicatorMarginLeft = dp2px(indicatorMarginLeft); + this.mIndicatorMarginTop = dp2px(indicatorMarginTop); + this.mIndicatorMarginRight = dp2px(indicatorMarginRight); + this.mIndicatorMarginBottom = dp2px(indicatorMarginBottom); + invalidate(); + } + + public void setIndicatorWidthEqualTitle(boolean indicatorWidthEqualTitle) { + this.mIndicatorWidthEqualTitle = indicatorWidthEqualTitle; + invalidate(); + } + + public void setUnderlineColor(int underlineColor) { + this.mUnderlineColor = underlineColor; + invalidate(); + } + + public void setUnderlineHeight(float underlineHeight) { + this.mUnderlineHeight = dp2px(underlineHeight); + invalidate(); + } + + public void setUnderlineGravity(int underlineGravity) { + this.mUnderlineGravity = underlineGravity; + invalidate(); + } + + public void setDividerColor(int dividerColor) { + this.mDividerColor = dividerColor; + invalidate(); + } + + public void setDividerWidth(float dividerWidth) { + this.mDividerWidth = dp2px(dividerWidth); + invalidate(); + } + + public void setDividerPadding(float dividerPadding) { + this.mDividerPadding = dp2px(dividerPadding); + invalidate(); + } + + public void setTextSelectsize(float textsize) { + this.mTextSelectSize = sp2px(textsize); + updateTabStyles(); + } + + public void setTextUnselectSize(int textSize) { + this.mTextUnSelectSize = 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 getTextSelectSize() { + return mTextSelectSize; + } + + public float getTextUnselectSize() { + return mTextUnSelectSize; + } + + 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); + return (TextView) tabView.findViewById(R.id.tv_tab_title); + } + + //setter and getter + + // show MsgTipView + private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private SparseBooleanArray mInitSetMap = new SparseBooleanArray(); + + /** + * 显示未读消息 + * + * @param position 显示tab位置 + * @param num num小于等于0显示红点,num大于0显示数字 + */ + public void showMsg(int position, int num) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + UnreadMsgUtils.show(tipView, num); + + if (mInitSetMap.get(position)) { + return; + } + + setMsgMargin(position, 4, 2); + mInitSetMap.put(position, true); + } + } + + /** + * 显示未读红点 + * + * @param position 显示tab位置 + */ + public void showDot(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + showMsg(position, 0); + } + + /** + * 隐藏未读消息 + */ + public void hideMsg(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = 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 = tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + TextView tv_tab_title = tabView.findViewById(R.id.tv_tab_title); + mTextPaint.setTextSize(position == mCurrentTab ? mTextSelectSize : mTextUnSelectSize); + float textWidth = mTextPaint.measureText(tv_tab_title.getText().toString()); + float textHeight = mTextPaint.descent() - mTextPaint.ascent(); + MarginLayoutParams lp = (MarginLayoutParams) tipView.getLayoutParams(); + lp.leftMargin = mTabWidth >= 0 ? (int) (mTabWidth / 2 + textWidth / 2 + dp2px(leftPadding)) : (int) (mTabPadding + textWidth + dp2px(leftPadding)); + lp.topMargin = mHeight > 0 ? (int) (mHeight - textHeight) / 2 - dp2px(bottomPadding) : 0; + tipView.setLayoutParams(lp); + } + } + + /** + * 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 + */ + public MsgView getMsgView(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = 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 fragments; + private String[] titles; + + public InnerPagerAdapter(FragmentManager fm, ArrayList fragments, String[] titles) { + super(fm); + this.fragments = fragments; + this.titles = titles; + } + + @Override + public int getCount() { + return fragments.size(); + } + + @Override + public CharSequence getPageTitle(int position) { + return titles[position]; + } + + @Override + public Fragment getItem(int position) { + return fragments.get(position); + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + // 覆写destroyItem并且空实现,这样每个Fragment中的视图就不会被销毁 + // super.destroyItem(container, position, object); + } + + @Override + public int getItemPosition(Object object) { + return PagerAdapter.POSITION_NONE; + } + } + + @Override + protected Parcelable onSaveInstanceState() { + Bundle bundle = new Bundle(); + bundle.putParcelable("instanceState", super.onSaveInstanceState()); + bundle.putInt("mCurrentTab", mCurrentTab); + return bundle; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state instanceof Bundle) { + Bundle bundle = (Bundle) state; + mCurrentTab = bundle.getInt("mCurrentTab"); + state = bundle.getParcelable("instanceState"); + if (mCurrentTab != 0 && mTabsContainer.getChildCount() > 0) { + updateTabSelection(mCurrentTab); + scrollToCurrentTab(); + } + } + super.onRestoreInstanceState(state); + } + + protected int dp2px(float dp) { + final float scale = mContext.getResources().getDisplayMetrics().density; + return (int) (dp * scale + 0.5f); + } + + protected int sp2px(float sp) { + final float scale = this.mContext.getResources().getDisplayMetrics().scaledDensity; + return (int) (sp * scale + 0.5f); + } +} diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/listener/CustomTabEntity.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/listener/CustomTabEntity.java new file mode 100644 index 0000000..ee39fe7 --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/listener/CustomTabEntity.java @@ -0,0 +1,13 @@ +package com.flyco.tablayout.listener; + +import androidx.annotation.DrawableRes; + +public interface CustomTabEntity { + String getTabTitle(); + + @DrawableRes + int getTabSelectedIcon(); + + @DrawableRes + int getTabUnselectedIcon(); +} \ No newline at end of file diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/listener/OnTabSelectListener.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/listener/OnTabSelectListener.java new file mode 100644 index 0000000..903a5fd --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/listener/OnTabSelectListener.java @@ -0,0 +1,7 @@ +package com.flyco.tablayout.listener; + +public interface OnTabSelectListener { + void onTabSelect(int position); + + void onTabReselect(int position); +} \ No newline at end of file diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/transformer/ExtendTransformer.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/transformer/ExtendTransformer.java new file mode 100644 index 0000000..2c508aa --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/transformer/ExtendTransformer.java @@ -0,0 +1,53 @@ +package com.flyco.tablayout.transformer; + +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.viewpager.widget.ViewPager; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by li.zhipeng on 2019/1/3. + *

+ * tab切换的 + */ +public class ExtendTransformer implements ViewPager.PageTransformer { + + private ArrayList transformers = new ArrayList<>(); + + + public ExtendTransformer() { + } + + public void addViewPagerTransformer(IViewPagerTransformer transformer) { + if (!transformers.contains(transformer)) { + transformers.add(transformer); + } + } + + public void removeViewPagerTransformer(IViewPagerTransformer transformer) { + transformers.remove(transformer); + } + + public List getTransformers() { + return transformers; + } + + public void setTransformers(List transformers) { + this.transformers.addAll(transformers); + } + + @Override + public void transformPage(@NonNull View view, final float position) { + // 回调设置的页面切换效果设置 + if (transformers != null && transformers.size() > 0) { + for (IViewPagerTransformer transformer : transformers) { + transformer.transformPage(view, position); + } + } + } + + +} diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/transformer/ITabScaleTransformer.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/transformer/ITabScaleTransformer.java new file mode 100644 index 0000000..145495c --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/transformer/ITabScaleTransformer.java @@ -0,0 +1,7 @@ +package com.flyco.tablayout.transformer; + +public interface ITabScaleTransformer { + void setNormalWidth(int position, int width, boolean isSelect); + + void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); +} diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/transformer/IViewPagerTransformer.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/transformer/IViewPagerTransformer.java new file mode 100644 index 0000000..e76544b --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/transformer/IViewPagerTransformer.java @@ -0,0 +1,12 @@ +package com.flyco.tablayout.transformer; + +import androidx.viewpager.widget.ViewPager; + +/** + * Created by li.zhipeng on 2019/1/3. + *

+ * ViewPager的扩展Transformer,配合SlidingScaleTabLayout使用 + * 因为字体的切换效果设置了默认的Transformer,所以扩展此接口 + */ +public interface IViewPagerTransformer extends ViewPager.PageTransformer { +} diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/transformer/TabScaleTransformer.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/transformer/TabScaleTransformer.java new file mode 100644 index 0000000..5757d64 --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/transformer/TabScaleTransformer.java @@ -0,0 +1,110 @@ +package com.flyco.tablayout.transformer; + +import android.util.Log; +import android.util.TypedValue; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.flyco.tablayout.SlidingScaleTabLayout; + +/** + * Created by li.zhipeng on 2019/1/3. + *

+ * tab切换的 + */ +public class TabScaleTransformer implements ITabScaleTransformer { + + private SlidingScaleTabLayout slidingScaleTabLayout; + + private float textSelectSize; + + private float textUnSelectSize; + +// private float maxScale; + + private boolean openDmg; + + public TabScaleTransformer(SlidingScaleTabLayout slidingScaleTabLayout, + float textSelectSize, float textUnSelectSize, boolean openDmg) { + this.slidingScaleTabLayout = slidingScaleTabLayout; + this.textSelectSize = textSelectSize; + this.textUnSelectSize = textUnSelectSize; +// this.maxScale = (textSelectSize / textUnSelectSize) - 1; + this.openDmg = openDmg; + } + + @Override + public void setNormalWidth(int position, int width, boolean isSelect) { + } + + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + Log.i("TabScaleTransformer", "position:" + position); + // 字体大小相同,不需要切换 + if (textSelectSize == textUnSelectSize) return; + if (openDmg) { + for (int i = 0; i < slidingScaleTabLayout.getTabCount(); i++) { + if (i != position && i != position + 1) { + changTabDmgWidth(i, 0); + } + } + changeDmgSize(position, positionOffset); + } else { + for (int i = 0; i < slidingScaleTabLayout.getTabCount(); i++) { + if (i != position && i != position + 1) { + updateTextSize(i, 1); + } + } + changeTextSize(position, positionOffset); + } + } + + private void changeTextSize(final int position, final float positionOffset) { + updateTextSize(position, positionOffset); + if (position + 1 < slidingScaleTabLayout.getTabCount()) { + updateTextSize(position + 1, 1 - positionOffset); + } + } + + private void updateTextSize(final int position, final float positionOffset) { + final TextView currentTab = slidingScaleTabLayout.getTitle(position); + // 必须要在View调用post更新样式,否则可能无效 + currentTab.post(new Runnable() { + @Override + public void run() { + int textSize = (int) (textSelectSize - Math.abs((textSelectSize - textUnSelectSize) * positionOffset)); + if (currentTab.getTextSize() != textSize) { + currentTab.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); + currentTab.requestLayout(); + } + } + }); + } + + private void changeDmgSize(final int position, final float positionOffset) { + slidingScaleTabLayout.post(new Runnable() { + @Override + public void run() { +// Log.i("lzp", "position:" + position + " positionOffset:" + positionOffset); + float scale = 1 - positionOffset; + changTabDmgWidth(position, scale); + if (position + 1 < slidingScaleTabLayout.getTabCount()) { + changTabDmgWidth(position + 1, positionOffset); + } + } + }); + } + + private void changTabDmgWidth(int position, float scale) { + final ImageView currentTabDmg = slidingScaleTabLayout.getDmgView(position); + if (currentTabDmg == null) return; + if (currentTabDmg.getDrawable() == null) return; + ViewGroup.LayoutParams params = currentTabDmg.getLayoutParams(); + int width = (int) (currentTabDmg.getMinimumWidth() + (currentTabDmg.getMaxWidth() - currentTabDmg.getMinimumWidth()) * scale); + if (params.width != width) { + params.width = width; + currentTabDmg.setLayoutParams(params); + } +// Log.i("lzp", "position:" + position + " scale:" + scale + " width:" + params.width); + } +} \ No newline at end of file diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/utils/FragmentChangeManager.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/utils/FragmentChangeManager.java new file mode 100644 index 0000000..72e5cf5 --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/utils/FragmentChangeManager.java @@ -0,0 +1,63 @@ +package com.flyco.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; + /** + * Fragment切换数组 + */ + private ArrayList mFragments; + /** + * 当前选中的Tab + */ + private int mCurrentTab; + + public FragmentChangeManager(FragmentManager fm, int containerViewId, ArrayList fragments) { + this.mFragmentManager = fm; + this.mContainerViewId = containerViewId; + this.mFragments = fragments; + initFragments(); + } + + /** + * 初始化fragments + */ + 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); + } +} \ No newline at end of file diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/utils/UnreadMsgUtils.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/utils/UnreadMsgUtils.java new file mode 100644 index 0000000..0446bfa --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/utils/UnreadMsgUtils.java @@ -0,0 +1,58 @@ +package com.flyco.tablayout.utils; + + +import android.util.DisplayMetrics; +import android.view.View; +import android.widget.RelativeLayout; + +import com.flyco.tablayout.widget.MsgView; + +/** + * 未读消息提示View,显示小红点或者带有数字的红点: + * 数字一位,圆 + * 数字两位,圆角矩形,圆角是高度的一半 + * 数字超过两位,显示99+ + */ +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 < 10) {//圆 + lp.width = (int) (18 * dm.density); + msgView.setText(num + ""); + } else if (num < 100) {//圆角矩形,圆角是高度的一半,设置默认padding + lp.width = RelativeLayout.LayoutParams.WRAP_CONTENT; + msgView.setPadding((int) (6 * dm.density), 0, (int) (6 * dm.density), 0); + msgView.setText(num + ""); + } else {//数字超过两位,显示99+ + 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); + } +} diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/utils/ViewUtils.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/utils/ViewUtils.java new file mode 100644 index 0000000..18ea77e --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/utils/ViewUtils.java @@ -0,0 +1,40 @@ +package com.flyco.tablayout.utils; + +import android.graphics.Bitmap; +import android.view.View; + +import androidx.annotation.IdRes; + +public class ViewUtils { + + public static Bitmap generateViewCacheBitmap(View view) { + view.destroyDrawingCache(); + int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + view.measure(widthMeasureSpec, heightMeasureSpec); + int width = view.getMeasuredWidth(); + int height = view.getMeasuredHeight(); + view.layout(0, 0, width, height); + view.setDrawingCacheEnabled(true); + view.buildDrawingCache(); + return Bitmap.createBitmap(view.getDrawingCache()); + } + + public static View findBrotherView(View view, @IdRes int id, int level) { + int count = 0; + View temp = view; + while (count < level) { + View target = temp.findViewById(id); + if (target != null) { + return target; + } + count += 1; + if (temp.getParent() instanceof View) { + temp = (View) temp.getParent(); + } else { + break; + } + } + return null; + } +} diff --git a/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/widget/MsgView.java b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/widget/MsgView.java new file mode 100644 index 0000000..d7c78f4 --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/java/com/flyco/tablayout/widget/MsgView.java @@ -0,0 +1,159 @@ +package com.flyco.tablayout.widget; + +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.flyco.tablayout.R; + +/** + * 用于需要圆角矩形框背景的TextView的情况,减少直接使用TextView时引入的shape资源文件 + */ +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 = dp2px(cornerRadius); + setBgSelector(); + } + + public void setStrokeWidth(int strokeWidth) { + this.strokeWidth = dp2px(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; + } + + protected int dp2px(float dp) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dp * scale + 0.5f); + } + + protected int sp2px(float sp) { + final float scale = this.context.getResources().getDisplayMetrics().scaledDensity; + return (int) (sp * scale + 0.5f); + } + + 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); + } + } +} diff --git a/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_scale_tab.xml b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_scale_tab.xml new file mode 100644 index 0000000..1533d51 --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_scale_tab.xml @@ -0,0 +1,38 @@ + + + + + + + + + + \ No newline at end of file diff --git a/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab.xml b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab.xml new file mode 100644 index 0000000..05d3232 --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab.xml @@ -0,0 +1,29 @@ + + + + + + + + \ No newline at end of file diff --git a/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_bottom.xml b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_bottom.xml new file mode 100644 index 0000000..17ba69a --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_bottom.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_left.xml b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_left.xml new file mode 100644 index 0000000..b5db8fb --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_left.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_right.xml b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_right.xml new file mode 100644 index 0000000..572f9a5 --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_right.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_segment.xml b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_segment.xml new file mode 100644 index 0000000..965cdcd --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_segment.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_top.xml b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_top.xml new file mode 100644 index 0000000..210ee30 --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/res/layout/layout_tab_top.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/FlycoTabLayoutZ_Lib/src/main/res/values/attrs.xml b/FlycoTabLayoutZ_Lib/src/main/res/values/attrs.xml new file mode 100644 index 0000000..324c0ca --- /dev/null +++ b/FlycoTabLayoutZ_Lib/src/main/res/values/attrs.xml @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index b236b8b..b19725c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,5 +1,4 @@ apply plugin: 'com.android.application' -apply plugin: "com.tencent.android.tpns" static def appName() { return "FLYSN" @@ -78,8 +77,8 @@ android { official { flavorDimensions "default" - versionCode 87 - versionName "3.4.7" + versionCode 88 + versionName "3.4.8" } } @@ -208,7 +207,7 @@ android { MT6789Debug.initWith(debug) MT6789Debug { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "63e2c211ad3bf161969582a58cf3c598" ] buildConfigField "String", "platform", '"G12NL"' versionNameSuffix "-debug" @@ -219,7 +218,7 @@ android { MT6789Release.initWith(release) MT6789Release { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "63e2c211ad3bf161969582a58cf3c598" ] buildConfigField "String", "platform", '"G12NL"' signingConfig signingConfigs.MT6789 @@ -228,7 +227,7 @@ android { Huaruian8768Debug.initWith(debug) Huaruian8768Debug { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "a4d58ed320000359544e99e1189438c7" ] buildConfigField "String", "platform", '"G10J"' versionNameSuffix "-debug" @@ -239,7 +238,7 @@ android { Huaruian8768Release.initWith(release) Huaruian8768Release { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "a4d58ed320000359544e99e1189438c7" ] buildConfigField "String", "platform", '"G10J"' signingConfig signingConfigs.Huaruian8768 @@ -248,7 +247,7 @@ android { iPlay50SEDebug.initWith(debug) iPlay50SEDebug { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "adfc5099b8305d05bff03dcfd6579640" ] buildConfigField "String", "platform", '"ipaly50"' versionNameSuffix "-debug" @@ -259,7 +258,7 @@ android { iPlay50SERelease.initWith(release) iPlay50SERelease { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "adfc5099b8305d05bff03dcfd6579640" ] buildConfigField "String", "platform", '"ipaly50"' signingConfig signingConfigs.iPlay50SE @@ -268,7 +267,7 @@ android { unisocDebug.initWith(debug) unisocDebug { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "a45f52890415873d7fe97731b9ff27a7" ] buildConfigField "String", "platform", '"ZhanRui"' versionNameSuffix "-debug" @@ -279,7 +278,7 @@ android { unisocRelease.initWith(debug) unisocRelease { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "a45f52890415873d7fe97731b9ff27a7" ] buildConfigField "String", "platform", '"ZhanRui"' debuggable true @@ -289,7 +288,7 @@ android { mtk11Debug.initWith(debug) mtk11Debug { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "2faeb0552117ccbbeb2fd63afd5d71f3" ] buildConfigField "String", "platform", '"MTK"' versionNameSuffix "-debug" @@ -300,7 +299,7 @@ android { mtk11Release.initWith(release) mtk11Release { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "2faeb0552117ccbbeb2fd63afd5d71f3" ] buildConfigField "String", "platform", '"MTK"' signingConfig signingConfigs.mtkAndroid11 @@ -309,7 +308,7 @@ android { teclastMTKDebug.initWith(debug) teclastMTKDebug { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "4ba0125745b17d0c73a6638dcda43d2f" ] buildConfigField "String", "platform", '"T30PRO"' versionNameSuffix "-debug" @@ -320,7 +319,7 @@ android { teclastMTKRelease.initWith(release) teclastMTKRelease { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "4ba0125745b17d0c73a6638dcda43d2f" ] buildConfigField "String", "platform", '"T30PRO"' signingConfig signingConfigs.teclastMTK @@ -329,7 +328,7 @@ android { G6Debug.initWith(debug) G6Debug { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "418069ea951c42cdaa39a4d2015f23b9" ] buildConfigField "String", "platform", '"G6"' versionNameSuffix "-debug" @@ -340,7 +339,7 @@ android { G6Release.initWith(release) G6Release { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "418069ea951c42cdaa39a4d2015f23b9" ] buildConfigField "String", "platform", '"G6"' signingConfig signingConfigs.G10P @@ -349,7 +348,7 @@ android { G13Debug.initWith(debug) G13Debug { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "418069ea951c42cdaa39a4d2015f23b9" ] buildConfigField "String", "platform", '"G13"' versionNameSuffix "-debug" @@ -360,7 +359,7 @@ android { G13Release.initWith(release) G13Release { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "418069ea951c42cdaa39a4d2015f23b9" ] buildConfigField "String", "platform", '"G13"' signingConfig signingConfigs.G10P @@ -369,7 +368,7 @@ android { Teclast8515Debug.initWith(debug) Teclast8515Debug { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "29db21d44be7ae2cadb6ea7189ebec72" ] buildConfigField "String", "platform", '"8515"' versionNameSuffix "-debug" @@ -380,7 +379,7 @@ android { Teclast8515Release.initWith(release) Teclast8515Release { manifestPlaceholders = [ - AK: "7IubK1Ugeuxga4KKC5VQyjTeQlExsYZq" + AMAP_KEY: "29db21d44be7ae2cadb6ea7189ebec72" ] buildConfigField "String", "platform", '"8515"' signingConfig signingConfigs.Teclast8515 @@ -390,7 +389,7 @@ android { teclastUnisocdebug.initWith(zhanRuiDebug) teclastUnisocdebug { manifestPlaceholders = [ - AK: "u5qGsILQ7qlXI8GDv6T6cGl8IWMtsPSu" + AMAP_KEY: "ef180363f53f3ea07af84be26b797f5d" ] buildConfigField "String", "platform", '"M40SE"' versionNameSuffix "-debug" @@ -401,7 +400,7 @@ android { teclastUnisocrelease.initWith(zhanRuiDebug) teclastUnisocrelease { manifestPlaceholders = [ - AK: "u5qGsILQ7qlXI8GDv6T6cGl8IWMtsPSu" + AMAP_KEY: "ef180363f53f3ea07af84be26b797f5d" ] buildConfigField "String", "platform", '"M40SE"' signingConfig signingConfigs.teclastUnisoc @@ -410,7 +409,7 @@ android { teclastUnisocUserdebug.initWith(zhanRuiDebug) teclastUnisocUserdebug { manifestPlaceholders = [ - AK: "u5qGsILQ7qlXI8GDv6T6cGl8IWMtsPSu" + AMAP_KEY: "a89c464a7e619791d65bf683602b9e30" ] buildConfigField "String", "platform", '"M40SE"' versionNameSuffix "-debug" @@ -421,7 +420,7 @@ android { zhanRuiDebug.initWith(debug) zhanRuiDebug { manifestPlaceholders = [ - AK: "EiqcGW9LWDvfMKl7mZxUtt1UkNKpdQI5" + AMAP_KEY: "63d3bf78053d530926309bb25e007e1a" ] buildConfigField "String", "platform", '"ZhanRui"' versionNameSuffix "-debug" @@ -432,7 +431,7 @@ android { zhanRuiRelease.initWith(release) zhanRuiRelease { manifestPlaceholders = [ - AK: "EiqcGW9LWDvfMKl7mZxUtt1UkNKpdQI5" + AMAP_KEY: "63d3bf78053d530926309bb25e007e1a" ] buildConfigField "String", "platform", '"ZhanRui"' signingConfig signingConfigs.zhanRui @@ -441,7 +440,7 @@ android { zhanRuiUserdebugReleas.initWith(debug) zhanRuiUserdebugReleas { manifestPlaceholders = [ - AK: "EiqcGW9LWDvfMKl7mZxUtt1UkNKpdQI5" + AMAP_KEY: "4ebbc3a36c028f6749fed5257f17c77e" ] buildConfigField "String", "platform", '"ZhanRui"' signingConfig signingConfigs.zhanRuiUserdebug @@ -450,6 +449,9 @@ android { debug { buildConfigField "String", "platform", '"MTK"' versionNameSuffix "-debug" + manifestPlaceholders = [ + AMAP_KEY: "9b4bdfa60aaacaf490356fc2e4e3ad0a" + ] //Zipalign优化 zipAlignEnabled true minifyEnabled false @@ -457,7 +459,7 @@ android { applicationVariants.all { variant -> variant.outputs.each { output -> if (outputFile != null) { - def fileName = "${appName()}-${variant.versionCode}-V${variant.versionName}-${releaseTime()}-${buildType.name}.apk" + def fileName = "${appName()}_${variant.versionCode}_V${variant.versionName}_${releaseTime()}_${buildType.name}.apk" output.outputFileName = fileName } } @@ -466,6 +468,9 @@ android { release { buildConfigField "String", "platform", '"MTK"' + manifestPlaceholders = [ + AMAP_KEY: "9b4bdfa60aaacaf490356fc2e4e3ad0a" + ] //Zipalign优化 zipAlignEnabled true //混淆 @@ -479,7 +484,7 @@ android { variant.outputs.each { output -> def outputFile = "" if (outputFile != null) { - def fileName = "${appName()}-${variant.versionCode}-V${variant.versionName}-${releaseTime()}-${buildType.name}.apk" + def fileName = "${appName()}_${variant.versionCode}_V${variant.versionName}_${releaseTime()}_${buildType.name}.apk" output.outputFileName = new File(outputFile, fileName) } } @@ -499,6 +504,8 @@ dependencies { // implementation fileTree(dir: 'libs', include: ['*.jar']) compileOnly files('libs/framework.jar') + implementation project(path: ':FlycoTabLayoutZ_Lib') + //implementation 'com.android.support:multidex:1.0.3' implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' @@ -510,7 +517,7 @@ dependencies { androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' //okhttp - implementation 'com.squareup.okhttp3:okhttp:4.10.0' + implementation 'com.squareup.okhttp3:okhttp:4.8.1' //Retrofit implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' @@ -524,6 +531,10 @@ dependencies { implementation 'com.trello.rxlifecycle4:rxlifecycle-components:4.0.2' implementation 'com.trello.rxlifecycle4:rxlifecycle-components-preference:4.0.2' implementation 'com.trello.rxlifecycle4:rxlifecycle-android-lifecycle:4.0.2' + + implementation 'com.jakewharton.rxbinding4:rxbinding:4.0.0' + implementation 'com.jeremyliao:live-event-bus-x:1.7.3' + //Google implementation 'com.google.code.gson:gson:2.9.0' implementation 'com.google.zxing:core:3.5.0' @@ -541,18 +552,19 @@ dependencies { implementation 'com.tencent:mmkv-static:1.2.13' //bugly implementation 'com.tencent.bugly:crashreport:4.1.9.2' - //腾讯移动推送 TPNS - implementation 'com.tencent.tpns:tpns:1.4.4.2-release' +// //腾讯移动推送 TPNS +// implementation 'com.tencent.tpns:tpns:1.4.4.2-release' //阿里云推送 implementation 'com.aliyun.ams:alicloud-android-push:3.8.0' - //百度地图 - implementation 'com.baidu.lbsyun:BaiduMapSDK_Location:9.1.8' +// //百度地图 +// implementation 'com.baidu.lbsyun:BaiduMapSDK_Location:9.1.8' + //高德地图定位 + implementation 'com.amap.api:location:5.1.0' //工具类 implementation 'com.blankj:utilcodex:1.31.0' //autosize会改变第三方view的大小 //https://github.com/JessYanCoding/AndroidAutoSize //implementation 'me.jessyan:autosize:1.2.1' - implementation 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar' implementation 'com.github.chrisbanes:PhotoView:2.0.0' //沉浸状态栏 implementation 'com.gitee.zackratos:UltimateBarX:0.8.0' @@ -561,6 +573,8 @@ dependencies { // implementation 'com.king.view:splitedittext:1.0.0' //动态权限框架 // implementation 'com.hjq:xxpermissions:6.0' + // 吐司框架:https://github.com/getActivity/Toaster + implementation 'com.github.getActivity:Toaster:12.6' } preBuild { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a6aabb9..a066575 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -50,7 +50,7 @@ - + @@ -73,13 +73,6 @@ - - - - - @@ -104,20 +97,33 @@ android:theme="@style/ImmerseTheme" android:usesCleartextTraffic="true" tools:replace="android:allowBackup"> + + + + + + + + + + + android:name=".activity.home.HomeActivity" + android:launchMode="singleTask"> + + + android:theme="@style/DialogCloseOnTouchOutside" /> - - - - - - - - - - - - - - - - @@ -266,19 +253,16 @@ - - - - + + + + android:name="com.amap.api.v2.apikey" + android:value="${AMAP_KEY}" /> implements NetworkUtils.OnNetworkStatusChangedListener { + private static final String TAG = "MainActivity"; + + private String[] mAllTitle = new String[]{ +// "使用统计", + "设备信息",}; + + private List mFragments; + private FragmentManager mFragmentManager; + private BaseFragmentPagerAdapter mBaseFragmentPagerAdapter; + private ViewPager.OnPageChangeListener mListener; + private int defaultCurrent = 0; + + @Override + public boolean setNightMode() { + return true; + } + + @Override + public void onDisconnected() { + Log.e(TAG, "onDisconnected: "); + } + + @Override + public void onConnected(NetworkUtils.NetworkType networkType) { + Log.e(TAG, "onConnected: "); + } + + @Override + public int getLayoutId() { + return R.layout.activity_home; + } + + @Override + protected void initDataBinding() { + mViewModel.setCtx(this); + mViewModel.setLifecycle(getLifecycleSubject()); + mViewModel.setVDBinding(mViewDataBinding); + mViewDataBinding.setClick(new BtnClick()); + } + + @Override + public void initView() { + mFragments = new ArrayList<>(); +// mFragments.add(new UsageFragment()); + mFragments.add(new DeviceFragment()); + mFragmentManager = getSupportFragmentManager(); + mBaseFragmentPagerAdapter = new BaseFragmentPagerAdapter(mFragmentManager, mFragments); + mViewDataBinding.viewPager.setAdapter(mBaseFragmentPagerAdapter); + mViewDataBinding.viewPager.setOnPageChangeListener(mListener); + mViewDataBinding.viewPager.setOffscreenPageLimit(4); + mViewDataBinding.mainSlidingTabLayout.setViewPager(mViewDataBinding.viewPager, mAllTitle); + } + + @Override + public void initData() { + mViewModel.mSnInfoData.observe(this, new androidx.lifecycle.Observer>() { + @Override + public void onChanged(BaseResponse snInfoBaseResponse) { + if (snInfoBaseResponse != null) { + //设备已经绑定 + if (snInfoBaseResponse.code == 200) { + SnInfo snInfo = snInfoBaseResponse.data; + NetInterfaceManager.getInstance().checkDeviceType(snInfo.getType_id()); +// mViewDataBinding.tvBindStatu.setText("设备已绑定"); + } + //设备没有绑定 + else if (snInfoBaseResponse.code == 300) { + ControlManager.getInstance().setDisableSetting(); +// mViewDataBinding.tvBindStatu.setText("设备未绑定"); + } + //没有授权的设备 + else if (snInfoBaseResponse.code == 400) { + ToastUtil.show(getString(R.string.device_unauthorized)); + Log.e(TAG, "setSnInfo: " + getString(R.string.device_unauthorized)); + ControlManager.getInstance().setDisableSetting(); +// mViewDataBinding.tvBindStatu.setText("设备未绑定"); + } + } + mViewModel.getAllApp(); + mViewModel.checkUpdate(); + mViewModel.checkFXYUpdate(); + mViewModel.getOverallApp(); + } + }); + } + + @Override + protected void onResume() { + super.onResume(); + Log.e(TAG, "onResume: "); + } + + @Override + protected void onPause() { + super.onPause(); + Log.e(TAG, "onPause: "); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + Log.e(TAG, "onDestroy: "); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + Log.e(TAG, "onNewIntent: "); + + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == KeyEvent.ACTION_DOWN) { + lazyExit(); + return true; + } + return super.onKeyDown(keyCode, event); + } + + private boolean isDebugMode() { + if (DeviceManager.isDebugMode()) { + return true; + } else { + return (boolean) SPUtils.get(this, CommonConfig.userDebugMode, false); + } + } + + final static int DEBUGCOUNTS = 8;//点击次数 + final static long DEBUGDURATION = 4 * 1000;//规定有效时间 + long[] mDEBUGHits = new long[DEBUGCOUNTS]; + + private void enterUserDebug() { + //每次点击时,数组向前移动一位 + System.arraycopy(mDEBUGHits, 1, mDEBUGHits, 0, mDEBUGHits.length - 1); + //为数组最后一位赋值 + mDEBUGHits[mDEBUGHits.length - 1] = SystemClock.uptimeMillis(); + if (mDEBUGHits[0] >= SystemClock.uptimeMillis() - DEBUGDURATION) { + mDEBUGHits = new long[DEBUGCOUNTS]; //重新初始化数组 + if ((boolean) SPUtils.get(HomeActivity.this, CommonConfig.EnableDebug, false)) { + ToastUtil.show("已经是Debug模式"); + } else { + showDebugDialog(); + } + } + } + + private void showDebugDialog() { + UserDebugDialog dialog = new UserDebugDialog(this); + dialog.setOnClickBottomListener(new UserDebugDialog.OnClickBottomListener() { + @Override + public void onPositiveClick() { + if ("53680320".equals(dialog.getEdittext())) { + SPUtils.put(HomeActivity.this, CommonConfig.EnableDebug, true); + ToastUtil.show("进入用户Debug模式"); + } else { + ToastUtil.show("密码错误"); + } + dialog.dismiss(); + } + + @Override + public void onNegtiveClick() { + dialog.dismiss(); + } + }); + dialog.show(); + dialog.getWindow().setGravity(Gravity.CENTER); + dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + } + + + private long mPreClickTime; + + private void lazyExit() { + if (System.currentTimeMillis() - mPreClickTime > 3000) { + ToastUtil.show("再按一次,退出"); + mPreClickTime = System.currentTimeMillis(); + } else { + finish(); + } + } + + private final int COUNTS = 4; // 点击次数 + private final long DURATION = 2 * 1000; // 规定有效时间 + private long[] mHits = new long[COUNTS]; + + private void continuousClick(int count, long time) { + //每次点击时,数组向前移动一位 + System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); + //为数组最后一位赋值 + mHits[mHits.length - 1] = SystemClock.uptimeMillis(); + if (mHits[0] >= SystemClock.uptimeMillis() - DURATION) { + mHits = new long[COUNTS]; //重新初始化数组 + ToastUtil.show("正在检查更新"); + } + } + + + public class BtnClick { + + public void exit(View view) { + lazyExit(); + } + + public void debug(View view) { + if (isDebugMode()) { + enterUserDebug(); + } + } + + + } + +} diff --git a/app/src/main/java/com/fuying/sn/activity/home/HomeViewModel.java b/app/src/main/java/com/fuying/sn/activity/home/HomeViewModel.java new file mode 100644 index 0000000..b73ed00 --- /dev/null +++ b/app/src/main/java/com/fuying/sn/activity/home/HomeViewModel.java @@ -0,0 +1,109 @@ +package com.fuying.sn.activity.home; + +import android.graphics.Bitmap; +import android.util.Log; + +import androidx.lifecycle.MutableLiveData; + +import com.fuying.sn.base.mvvm.BaseViewModel; +import com.fuying.sn.bean.BaseResponse; +import com.fuying.sn.bean.SnInfo; +import com.fuying.sn.config.CommonConfig; +import com.fuying.sn.databinding.ActivityHomeBinding; +import com.fuying.sn.network.NetInterfaceManager; +import com.fuying.sn.utils.CXAESUtil; +import com.fuying.sn.utils.Utils; +import com.trello.rxlifecycle4.android.ActivityEvent; + +import io.reactivex.rxjava3.disposables.Disposable; + +public class HomeViewModel extends BaseViewModel { + + @Override + public ActivityHomeBinding getVDBinding() { + return binding; + } + + @Override + public void onDestroy() { + + } + + + public MutableLiveData> mSnInfoData = new MutableLiveData<>(); + + public void getSnInfo() { + NetInterfaceManager.getInstance() + .getSnInfo(getLifecycle(), new NetInterfaceManager.ObserverCallback() { + @Override + public void onSubscribe(Disposable d) { + Log.e("getSnInfo", "onSubscribe: "); + } + + @Override + public void onNext(BaseResponse response) { + Log.e("getSnInfo", "onNext: " + response); + mSnInfoData.setValue(response); + } + + @Override + public void onError(Throwable e) { + Log.e("getSnInfo", "onError: " + e.getMessage()); +// String jsonString = mCacheHelper.getAsString(UrlAddress.SN_INFO); +// Gson gson = new Gson(); +// Type type = new TypeToken>() { +// }.getType(); +// BaseResponse userInfoBaseResponse = gson.fromJson(jsonString, type); +// mSnInfoData.setValue(userInfoBaseResponse); + } + + @Override + public void onComplete() { + Log.e("getSnInfo", "onComplete: "); + } + }); + } + + public MutableLiveData mQRCodeData = new MutableLiveData<>(); + + public void getQRCode() { + String encryptString = CXAESUtil.encrypt(CommonConfig.AES_KEY, Utils.getIMEI(getCtx())); + Log.e("getQRCode", "setImageAndText: " + encryptString); + Bitmap bitmap = Utils.createQRImage(encryptString, 400, 400); + mQRCodeData.setValue(bitmap); + } + + public void getAllApp() { + NetInterfaceManager.getInstance().getAppWhiteList(new NetInterfaceManager.WhiteListCallback() { + @Override + public void onComplet() { + } + }); + } + + public void checkUpdate() { + NetInterfaceManager.getInstance().checkAllAppUpdate(true, getLifecycle(), new NetInterfaceManager.CompleteCallback() { + @Override + public void onComplete() { + } + }); + } + + public void checkFXYUpdate() { +// NetInterfaceManager.getInstance().checkFXYAppUpdate(true, getLifecycle(), new NetInterfaceManager.CompleteCallback() { +// @Override +// public void onComplete() { +// mView.checkFXYUpdateFinish(); +// } +// }); + } + + public void getOverallApp() { + NetInterfaceManager.getInstance().getOverallApp(true, getLifecycle(), new NetInterfaceManager.CompleteCallback() { + @Override + public void onComplete() { + + } + }); + } +} diff --git a/app/src/main/java/com/fuying/sn/activity/main/MainActivity.java b/app/src/main/java/com/fuying/sn/activity/main/MainActivity.java index 6b5ec8c..d1fb33d 100644 --- a/app/src/main/java/com/fuying/sn/activity/main/MainActivity.java +++ b/app/src/main/java/com/fuying/sn/activity/main/MainActivity.java @@ -46,7 +46,7 @@ import com.fuying.sn.service.GuardService; import com.fuying.sn.service.ManagerService; import com.fuying.sn.service.StepService; import com.fuying.sn.service.main.MainService; -import com.fuying.sn.utils.JGYUtils; +import com.fuying.sn.utils.JgyUtils; import com.fuying.sn.utils.SPUtils; import com.fuying.sn.utils.TimeUtils; import com.fuying.sn.utils.ToastUtil; @@ -110,9 +110,9 @@ public class MainActivity extends BaseMvvmActivity>() { }.getType(); @@ -109,6 +109,7 @@ public class MainViewModel extends BaseViewModel { + + private AppInfo mAppInfoData; + + + @Override + protected int getLayoutId() { + return R.layout.activity_update; + } + + @Override + protected void initDataBinding() { + mViewModel.setCtx(this); + mViewModel.setLifecycle(getLifecycleSubject()); + mViewModel.setVDBinding(mViewDataBinding); + mViewDataBinding.setClick(new BtnClick()); + } + + @Override + protected void initView() { + + } + + @Override + protected void initData() { + Intent intent = getIntent(); + mAppInfoData = (AppInfo) intent.getSerializableExtra("appInfo"); + mViewDataBinding.setAppUpdateInfo(mAppInfoData); + mViewDataBinding.setMsg("检测到新版本,是否更新"); + } + + + public class BtnClick { + public void empty(View view) { + + } + + public void exit(View view) { + finish(); + } + + public void upgrade(View view) { + Intent intent = new Intent(UpdateActivity.this, DownloadService.class); +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { +// startForegroundService(intent); +// } else { + startService(intent); +// } + if (mAppInfoData != null) { + DownloadEntity entity = Aria.download(this).getFirstDownloadEntity(mAppInfoData.getApp_url()); + if (null != entity) { + if (entity.isComplete()) { + ApkUtils.installApp(UpdateActivity.this, entity.getFilePath()); + } else { + if (entity.getState() == STATE_RUNNING) { + Toaster.show("文件正在下载中"); + finish(); + } else { + Aria.download(this).resumeAllTask(); + Toaster.show("正在下载"); + finish(); + } + } + } else { + ApkUtils.checkAppUpdate(UpdateActivity.this, mAppInfoData); + Toaster.show("正在下载更新"); + finish(); + } + } + + } + } +} diff --git a/app/src/main/java/com/fuying/sn/activity/update/UpdateViewModel.java b/app/src/main/java/com/fuying/sn/activity/update/UpdateViewModel.java new file mode 100644 index 0000000..9d693fa --- /dev/null +++ b/app/src/main/java/com/fuying/sn/activity/update/UpdateViewModel.java @@ -0,0 +1,18 @@ +package com.fuying.sn.activity.update; + +import com.fuying.sn.base.mvvm.BaseViewModel; +import com.fuying.sn.databinding.ActivityUpdateBinding; +import com.trello.rxlifecycle4.android.ActivityEvent; + +public class UpdateViewModel extends BaseViewModel { + + @Override + public ActivityUpdateBinding getVDBinding() { + return binding; + } + + @Override + public void onDestroy() { + + } +} diff --git a/app/src/main/java/com/fuying/sn/base/BaseApplication.java b/app/src/main/java/com/fuying/sn/base/BaseApplication.java index e2bf372..6cc0cae 100644 --- a/app/src/main/java/com/fuying/sn/base/BaseApplication.java +++ b/app/src/main/java/com/fuying/sn/base/BaseApplication.java @@ -31,18 +31,13 @@ import com.fuying.sn.service.ManagerService; import com.fuying.sn.service.StepService; import com.fuying.sn.service.main.MainService; import com.fuying.sn.utils.AppUsedTimeUtils; -import com.fuying.sn.utils.JGYUtils; +import com.fuying.sn.utils.JgyUtils; import com.fuying.sn.utils.SystemUtils; import com.fuying.sn.utils.Utils; -import com.tencent.android.tpush.XGIOperateCallback; -import com.tencent.android.tpush.XGPushConfig; -import com.tencent.android.tpush.XGPushManager; +import com.hjq.toast.Toaster; import com.tencent.bugly.crashreport.CrashReport; import com.tencent.mmkv.MMKV; -import java.util.ArrayList; -import java.util.List; - public class BaseApplication extends Application { private static final String TAG = "BaseApplication"; @@ -79,9 +74,9 @@ public class BaseApplication extends Application { PushManager.init(this); aliyunPushInit(); - tPushInit(); - JGYUtils.init(this); + Toaster.init(this); + JgyUtils.init(this); CrashReport.initCrashReport(getApplicationContext(), "e5f026c8d5", false); CrashReport.setDeviceId(this, Utils.getSerial()); @@ -97,7 +92,7 @@ public class BaseApplication extends Application { AmapManager.init(this); NetInterfaceManager.init(this); AppUsedTimeUtils.init(this); - JGYUtils.hookWebView(); + JgyUtils.hookWebView(); startService(); } @@ -196,36 +191,4 @@ public class BaseApplication extends Application { }); } - private void tPushInit() { - XGPushConfig.enableDebug(this, true); - XGPushConfig.enablePullUpOtherApp(this, false); - XGPushManager.registerPush(this, new XGIOperateCallback() { - @Override - public void onSuccess(Object data, int flag) { - //token在设备卸载重装的时候有可能会变 - Log.e("TPush", "注册成功,设备token为:" + data); - List accountInfoList = new ArrayList<>(); - Log.e("TPush", "onSuccess: " + Utils.getSerial()); - accountInfoList.add(new XGPushManager.AccountInfo(XGPushManager.AccountType.CUSTOM.getValue(), Utils.getSerial())); -// accountInfoList.add(new XGPushManager.AccountInfo(XGPushManager.AccountType.CUSTOM.getValue(), Utils.getIMEI(getApplicationContext()))); - XGPushManager.upsertAccounts(getApplicationContext(), accountInfoList, new XGIOperateCallback() { - @Override - public void onSuccess(Object data, int flag) { - Log.e("TPush", "upsertAccounts onSuccess, data:" + data + ", flag:" + flag); - NetInterfaceManager.getInstance().setPushTags(); - } - - @Override - public void onFail(Object data, int errCode, String msg) { - Log.e("TPush", "upsertAccounts onFail, data:" + data + ", code:" + errCode + ", msg:" + msg); - } - }); - } - - @Override - public void onFail(Object data, int errCode, String msg) { - Log.e("TPush", "注册失败,错误码:" + errCode + ",错误信息:" + msg); - } - }); - } } diff --git a/app/src/main/java/com/fuying/sn/base/BaseFragment.java b/app/src/main/java/com/fuying/sn/base/BaseFragment.java new file mode 100644 index 0000000..a065368 --- /dev/null +++ b/app/src/main/java/com/fuying/sn/base/BaseFragment.java @@ -0,0 +1,44 @@ +package com.fuying.sn.base; + +import android.os.Bundle; + +import com.fuying.sn.base.rx.BaseRxFragment; + +public abstract class BaseFragment extends BaseRxFragment { + + protected boolean isViewInitiated; + protected boolean isVisibleToUser; + protected boolean isDataInitiated; + + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + isViewInitiated = true; + prepareFetchData(); + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + this.isVisibleToUser = isVisibleToUser; + prepareFetchData(); + } + + public abstract void fetchData(); + + public boolean prepareFetchData() { + return prepareFetchData(false); + } + + public boolean prepareFetchData(boolean forceUpdate) { + if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) { + fetchData(); + //注释掉保证每次都更新数据 + isDataInitiated = true; + return true; + } + return false; + } + +} diff --git a/app/src/main/java/com/fuying/sn/base/mvvm/fragment/BaseMvvmDialogFragment.java b/app/src/main/java/com/fuying/sn/base/mvvm/fragment/BaseMvvmDialogFragment.java new file mode 100644 index 0000000..0c2efb0 --- /dev/null +++ b/app/src/main/java/com/fuying/sn/base/mvvm/fragment/BaseMvvmDialogFragment.java @@ -0,0 +1,184 @@ +package com.fuying.sn.base.mvvm.fragment; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; + +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.databinding.DataBindingUtil; +import androidx.databinding.ViewDataBinding; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; + +import com.fuying.sn.base.BaseDialogFragment; + +import java.lang.ref.WeakReference; +import java.lang.reflect.ParameterizedType; + +/** + * @author: lml + * @date: 2021/12/15 + */ +public abstract class BaseMvvmDialogFragment extends BaseDialogFragment { + protected String mTag = this.getClass().getSimpleName(); + /** + * 是否顯示了 + */ + protected boolean mIsVisible; + /** + * 是否準備好了-Created + */ + protected boolean mHasPrepare; + + + protected VM mViewModel; + protected VDB mViewDataBinding; + protected Class vmClass; + // +// protected Toolbar toolbar; +// protected View statusBarView; + // + protected Bundle bundle;//来自getArguments() + protected Bundle savedInstanceState; + +// protected Context context; + + /** + * 上下文 + */ + private WeakReference ctx; + + public Context getCtx() { + return ctx == null ? null : ctx.get(); + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); +// this.context = context; + ctx = new WeakReference<>(context); + } + + /** + * onCreate、onResume里不能调用 + * + * @return + */ + public boolean isAttached() { + boolean flag = getCtx() != null && isAdded(); + Log.e(" >> isAttached >>", "flag = " + flag); + return flag; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + //ViewDataBinding + mViewDataBinding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false); + mViewDataBinding.setLifecycleOwner(this); + + //ViewModel + vmClass = (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; + mViewModel = new ViewModelProvider(this).get(vmClass); + + return mViewDataBinding.getRoot(); + } + + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + initDataBinding(); + initView(bundle = getArguments()); + + initData(this.savedInstanceState = savedInstanceState); + + if (mIsVisible) { + onEnter(); + } + mHasPrepare = true; + + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + mHasPrepare = false; + mViewDataBinding = null; + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if (mIsVisible == getUserVisibleHint()) + return; + mIsVisible = getUserVisibleHint(); + if (mIsVisible) { + if (!mHasPrepare) + return; + onEnter(); + } else { + onExit(); + } + } + + @LayoutRes + protected abstract int getLayoutId(); + + protected abstract void initDataBinding(); + + protected abstract void initView(Bundle bundle); + + protected abstract void initData(Bundle savedInstanceState); + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + } + + protected void hideInputMethod(Activity activity) { + InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); + View view = activity.getCurrentFocus(); + if (view != null) { + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + } + + protected void hideInputMethod(Activity activity, EditText editText) { + InputMethodManager imm = (InputMethodManager) editText.getContext().getSystemService(Activity.INPUT_METHOD_SERVICE); + View view = activity.getCurrentFocus(); + if (view != null) { + imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + } + + protected void showInputMethod(EditText editText) { + InputMethodManager imm = (InputMethodManager) editText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(editText, InputMethodManager.SHOW_FORCED); + } + + /** + * 進入界面 + */ + protected void onEnter() { + + } + + /** + * 離開界面 + */ + protected void onExit() { + + } + +} diff --git a/app/src/main/java/com/fuying/sn/base/mvvm/fragment/BaseMvvmFragment.java b/app/src/main/java/com/fuying/sn/base/mvvm/fragment/BaseMvvmFragment.java new file mode 100644 index 0000000..824afe7 --- /dev/null +++ b/app/src/main/java/com/fuying/sn/base/mvvm/fragment/BaseMvvmFragment.java @@ -0,0 +1,279 @@ +package com.fuying.sn.base.mvvm.fragment; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; + +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.databinding.DataBindingUtil; +import androidx.databinding.ViewDataBinding; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; + +import com.fuying.sn.base.BaseFragment; + +import java.lang.ref.WeakReference; +import java.lang.reflect.ParameterizedType; + +/** + * @author: lml + * @date: 2021/12/15 + */ +public abstract class BaseMvvmFragment extends BaseFragment { + protected String mTag = this.getClass().getSimpleName(); + /** + * 是否顯示了 + */ + protected boolean mIsVisible; + /** + * 是否準備好了-Created + */ + protected boolean mHasPrepare; + + + protected VM mViewModel; + protected VDB mViewDataBinding; + protected Class vmClass; + // +// protected Toolbar toolbar; +// protected View statusBarView; + // + protected Bundle bundle;//来自getArguments() + protected Bundle savedInstanceState; + +// protected Context context; + + /** + * 上下文 + */ + private WeakReference ctx; + + public Context getCtx() { + return ctx == null ? null : ctx.get(); + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); +// this.context = context; + ctx = new WeakReference<>(context); + } + + /** + * onCreate、onResume里不能调用 + * + * @return + */ + public boolean isAttached() { + boolean flag = getCtx() != null && isAdded(); + Log.e(" >> isAttached >>", "flag = " + flag); + return flag; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + //ViewDataBinding + mViewDataBinding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false); + mViewDataBinding.setLifecycleOwner(this); + + //ViewModel + vmClass = (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; + mViewModel = new ViewModelProvider(this).get(vmClass); + // + return mViewDataBinding.getRoot(); + } + + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + +// if (initStatusBarToolBar()) { +// toolbar = getToolbar(); +// } + //注册eventbus +// if (getClass().isAnnotationPresent(BindEventBus.class)) +// EventBusManager.register(this); + // + +// fitsLayoutOverlap(); + initDataBinding(); + long time = System.currentTimeMillis(); + initView(bundle = getArguments()); + Log.e(this.getClass().getSimpleName(), "onViewCreated: initView " + (System.currentTimeMillis() - time) + "ms"); + // + long time2 = System.currentTimeMillis(); + initData(this.savedInstanceState = savedInstanceState); + Log.e(this.getClass().getSimpleName(), "onViewCreated: initData " + (System.currentTimeMillis() - time2) + "ms"); + // + if (mIsVisible) { + onEnter(); + } + mHasPrepare = true; + // +// LiveDataBus.get().with(ConstantUtils.DATA_BUS_LOADING_FRAGMENT, Boolean.class).observe(getActivity(), bool -> { +// L.e(" >> LiveDataBus >> DATA_BUS_LOADING_FRAGMENT: %s", bool); +// if(bool) { +// showLoading(R.string.str_please_wait); +// } else { +// hideLoading(); +// } +// }); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + mHasPrepare = false; + mViewDataBinding = null; + //移除eventbus +// if (getClass().isAnnotationPresent(BindEventBus.class)) +// EventBusManager.unregister(this); + // + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if (mIsVisible == getUserVisibleHint()) + return; + mIsVisible = getUserVisibleHint(); + if (mIsVisible) { + if (!mHasPrepare) + return; + onEnter(); + } else { + onExit(); + } + } + + @LayoutRes + protected abstract int getLayoutId(); + +// protected abstract Toolbar getToolbar(); + +// protected View getStatusView() { +// return null; +// } + + protected abstract void initDataBinding(); + + protected abstract void initView(Bundle bundle); + + protected abstract void initData(Bundle savedInstanceState); + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); +// fitsLayoutOverlap(); + } + +// protected boolean isImmersionBarEnabled() { +// return true; +// } + +// protected boolean initStatusBarToolBar() { +// return true; +// } + + +// private void fitsLayoutOverlap() { +// if (!isImmersionBarEnabled()) return; +// if (statusBarView != null) { +// ImmersionBar.setStatusBarView(getActivity(), statusBarView); +// } +// if (toolbar != null) { +// ImmersionBar.setTitleBar(getActivity(), toolbar); +// } +// } + + protected void hideInputMethod(Activity activity) { + InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); + View view = activity.getCurrentFocus(); + if (view != null) { + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + } + + protected void hideInputMethod(Activity activity, EditText editText) { + InputMethodManager imm = (InputMethodManager) editText.getContext().getSystemService(Activity.INPUT_METHOD_SERVICE); + View view = activity.getCurrentFocus(); + if (view != null) { + imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + } + + protected void showInputMethod(EditText editText) { + InputMethodManager imm = (InputMethodManager) editText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(editText, InputMethodManager.SHOW_FORCED); + } + + +// private CustomDialog mWaitDialog; +// +// public void showLoading(@StringRes int contentID) { +// showLoading(contentID, R.color.white); +// } +// +// public void showLoading(@StringRes int contentID, @ColorRes int color) { +// hideLoading(); +// DialogX.init(getActivity()); +// if (color == R.color.white) { +// mWaitDialog = DialogXUtil.getInstance().showLoading(getActivity(), getString(contentID), getResources().getColor(color)); +// } else { +// mWaitDialog = DialogXUtil.getInstance().showLoading_black(getActivity(), getString(contentID), getResources().getColor(color)); +// } +// } +// +// public void updateLoadingTip(@StringRes int messageID, int percent) { +// try { +// if (mWaitDialog != null && mWaitDialog.isShow()) { +// TextView tvTip = mWaitDialog.getCustomView().findViewById(R.id.tv_load_tip); +// if (tvTip != null) +// tvTip.setText(getResources().getString(messageID) + (percent == -1 ? "" : percent + "%")); +// } +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } +// +// public boolean isShowLoading() { +// return mWaitDialog != null && mWaitDialog.isShow(); +// } +// +// public void hideLoading() { +// try { +// boolean isShow = isShowLoading(); +// L.d(" >> hideLoading :: isShow: %s", isShow); +// if (isShow) +// mWaitDialog.dismiss(); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } + + /** + * 進入界面 + */ + protected void onEnter() { + + } + + /** + * 離開界面 + */ + protected void onExit() { + + } + +} diff --git a/app/src/main/java/com/fuying/sn/bean/MapBean.java b/app/src/main/java/com/fuying/sn/bean/MapBean.java new file mode 100644 index 0000000..bfdc196 --- /dev/null +++ b/app/src/main/java/com/fuying/sn/bean/MapBean.java @@ -0,0 +1,134 @@ +package com.fuying.sn.bean; + +import java.io.Serializable; + +public class MapBean implements Serializable { + private static final long serialVersionUID = -4356064111098876676L; + + double longitude; + double latitude; + String adcode; + String address; + String city; + String cityCode; + String country; + String countryCode; + String district; + String province; + String street; + String streetNumber; + String town; + String locationDescribe; + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + public double getLatitude() { + return latitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + public String getAdcode() { + return adcode; + } + + public void setAdcode(String adcode) { + this.adcode = adcode; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getCityCode() { + return cityCode; + } + + public void setCityCode(String cityCode) { + this.cityCode = cityCode; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getCountryCode() { + return countryCode; + } + + public void setCountryCode(String countryCode) { + this.countryCode = countryCode; + } + + public String getDistrict() { + return district; + } + + public void setDistrict(String district) { + this.district = district; + } + + public String getProvince() { + return province; + } + + public void setProvince(String province) { + this.province = province; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getStreetNumber() { + return streetNumber; + } + + public void setStreetNumber(String streetNumber) { + this.streetNumber = streetNumber; + } + + public String getTown() { + return town; + } + + public void setTown(String town) { + this.town = town; + } + + public String getLocationDescribe() { + return locationDescribe; + } + + public void setLocationDescribe(String locationDescribe) { + this.locationDescribe = locationDescribe; + } +} diff --git a/app/src/main/java/com/fuying/sn/config/CommonConfig.java b/app/src/main/java/com/fuying/sn/config/CommonConfig.java index 9af76a0..f1d75cd 100644 --- a/app/src/main/java/com/fuying/sn/config/CommonConfig.java +++ b/app/src/main/java/com/fuying/sn/config/CommonConfig.java @@ -3,6 +3,20 @@ package com.fuying.sn.config; public class CommonConfig { public static final String MMKV_ID = "InterProcessKV"; + public static final String MAP_LOCATION_JSON_KEY = "MAPLOCATION_JSON_STRING"; + public static final String MAP_LONGITUDE_KEY = "map_longitude_key"; + public static final String MAP_LATITUDE_KEY = "map_latitude_key"; + public static final String MAP_ADDRESS_KEY = "map_address_key"; + public static final String MAP_PROVINCE_KEY = "map_province_key"; + public static final String MAP_CITY_KEY = "map_city_key"; + public static final String MAP_DISTRICT_KEY = "map_district_key"; + public static final String MAP_STREET_KEY = "map_street_key"; + public static final String MAP_LOCATION_DESCRIBE_KEY = "map_locationDescribe_key"; + public static final String MAP_ERROR_KEY = "map_error_key"; + public static final String MAP_onLocationChanged_time_KEY = "map_onLocationChanged_time_key"; + public static final String MAP_BEAN = "MapBean"; + + /*首次开机*/ public static final String JGY_FIRST_BOOT = "first_boot"; /*保存的应用版本号*/ diff --git a/app/src/main/java/com/fuying/sn/desktop/RunningAppManager.java b/app/src/main/java/com/fuying/sn/desktop/RunningAppManager.java index 5a40ad2..4186794 100644 --- a/app/src/main/java/com/fuying/sn/desktop/RunningAppManager.java +++ b/app/src/main/java/com/fuying/sn/desktop/RunningAppManager.java @@ -38,7 +38,7 @@ import com.fuying.sn.gson.GsonUtils; import com.fuying.sn.network.NetInterfaceManager; import com.fuying.sn.network.UrlAddress; import com.fuying.sn.utils.AppUsedTimeUtils; -import com.fuying.sn.utils.JGYUtils; +import com.fuying.sn.utils.JgyUtils; import com.fuying.sn.utils.ToastUtil; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; @@ -188,13 +188,13 @@ public class RunningAppManager { private void checkForegroundAppName() { String topPackage = getTopActivityInfo(); if ("org.chromium.browser".equals(topPackage)) { - JGYUtils.getInstance().killPackage("org.chromium.browser"); + JgyUtils.getInstance().killPackage("org.chromium.browser"); } String appPackageName = getAppPackageName(); Log.d(TAG, "checkForegroundAppName: topPackage = " + topPackage); Log.d(TAG, "checkForegroundAppName: appPackageName = " + appPackageName); - if (!JGYUtils.getInstance().isScreenOn()) { + if (!JgyUtils.getInstance().isScreenOn()) { Log.d(TAG, "checkForegroundAppName: isScreenOn = false"); if (!TextUtils.isEmpty(appPackageName)) { Log.d(TAG, "checkForegroundAppName: isEmpty = false"); @@ -255,7 +255,7 @@ public class RunningAppManager { // removeTask(topPackage); NetInterfaceManager.getInstance().getAppTimeControl(); NetInterfaceManager.getInstance().getSnTimeControl(); - JGYUtils.getInstance().killPackage(appPackageName); + JgyUtils.getInstance().killPackage(appPackageName); killApp(); gotoLauncher(); } else { @@ -282,7 +282,7 @@ public class RunningAppManager { Log.i(TAG, "checkForegroundAppName: 没有剩余时间2"); // removeTask(topPackage); killApp(); - JGYUtils.getInstance().killPackage(appPackageName); + JgyUtils.getInstance().killPackage(appPackageName); gotoLauncher(); NetInterfaceManager.getInstance().getAppTimeControl(); NetInterfaceManager.getInstance().getSnTimeControl(); @@ -302,13 +302,13 @@ public class RunningAppManager { List appList = launcherApp.stream().map(resolveInfo -> resolveInfo.activityInfo.packageName).collect(Collectors.toList()); Log.e(TAG, "killApp: " + appList); for (String pkg : appList) { - if (JGYUtils.fuxiaoying.equals(pkg) + if (JgyUtils.fuxiaoying.equals(pkg) || BuildConfig.APPLICATION_ID.equals(pkg) || "com.android.settings".equals(pkg) ) { continue; } - JGYUtils.getInstance().killPackage(pkg); + JgyUtils.getInstance().killPackage(pkg); } } @@ -759,7 +759,7 @@ public class RunningAppManager { this.add("com.uiui.store"); this.add("com.uiui.info"); this.add("com.tt.ttutils"); - this.add(JGYUtils.fuxiaoying); + this.add(JgyUtils.fuxiaoying); this.add("com.sprd.engineermode"); this.add("com.teclast.update"); this.add("com.incar.update"); diff --git a/app/src/main/java/com/fuying/sn/fragment/device/DeviceFragment.java b/app/src/main/java/com/fuying/sn/fragment/device/DeviceFragment.java new file mode 100644 index 0000000..3969339 --- /dev/null +++ b/app/src/main/java/com/fuying/sn/fragment/device/DeviceFragment.java @@ -0,0 +1,156 @@ +package com.fuying.sn.fragment.device; + +import android.app.Activity; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.text.TextUtils; +import android.text.format.Formatter; +import android.util.Log; +import android.view.View; + +import androidx.lifecycle.Observer; + +import com.blankj.utilcode.constant.MemoryConstants; +import com.blankj.utilcode.util.ConvertUtils; +import com.fuying.sn.BuildConfig; +import com.fuying.sn.R; +import com.fuying.sn.activity.update.UpdateActivity; +import com.fuying.sn.base.mvvm.fragment.BaseMvvmFragment; +import com.fuying.sn.bean.AppInfo; +import com.fuying.sn.bean.SnInfo; +import com.fuying.sn.config.CommonConfig; +import com.fuying.sn.databinding.FragmentDeviceBinding; +import com.fuying.sn.utils.ApkUtils; +import com.fuying.sn.utils.JgyUtils; +import com.fuying.sn.utils.TimeUtils; +import com.fuying.sn.utils.Utils; +import com.hjq.toast.Toaster; +import com.jakewharton.rxbinding4.view.RxView; +import com.tencent.mmkv.MMKV; + +import io.reactivex.rxjava3.disposables.Disposable; + + +public class DeviceFragment extends BaseMvvmFragment { + private static final String TAG = "DeviceFragment"; + private Activity mContext; + + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + + private Disposable mClickDisposable; + // 2秒防抖时间 + private long windowDurationMs = 60000; + // 记录上次成功触发的时间 + private final long[] lastClickTime = {0}; + + @Override + protected int getLayoutId() { + return R.layout.fragment_device; + } + + @Override + protected void initDataBinding() { + mContext = getActivity(); + mViewModel.setCtx(getCtx()); + mViewModel.setLifecycle(getLifecycleSubject()); + mViewModel.setVDBinding(mViewDataBinding); + mViewDataBinding.setClick(new BtnClick()); + } + + @Override + protected void initView(Bundle bundle) { + Log.e(TAG, "initView: byte2MemorySize = " + ConvertUtils.byte2MemorySize(Utils.getTotalMem(mContext), MemoryConstants.GB)); + Log.e(TAG, "initView: getTotalMem = " + ConvertUtils.byte2FitMemorySize(Utils.getTotalMem(mContext))); + Log.e(TAG, "initView: getTotalMemory = " + Formatter.formatFileSize(mContext, Utils.getTotalMemory(mContext))); + + setDeviceInfo(); + + + mClickDisposable = RxView.clicks(mViewDataBinding.clUpdate) + .subscribe(o -> { + long currentTime = System.currentTimeMillis(); + if (currentTime - lastClickTime[0] >= windowDurationMs) { + // 【情况 A】满足时间间隔:执行核心逻辑 + lastClickTime[0] = currentTime; + mViewModel.checkUpdate(true); + } else { + // 【情况 B】在防抖时间内:仅提示 + Toaster.show("请稍后再试"); + } + }); + } + + @Override + protected void initData(Bundle savedInstanceState) { + mViewModel.mSnInfoMutableLiveData.observe(this, new Observer() { + @Override + public void onChanged(SnInfo snInfo) { + if (snInfo != null) { + if (!TextUtils.isEmpty(snInfo.getMobile())) { + mViewDataBinding.tvPhoneNumber.setText(snInfo.getMobile()); + } + mViewDataBinding.tvBindTime.setText(TimeUtils.getDate(0)); + } else { + mViewDataBinding.tvPhoneNumber.setText("未绑定"); + mViewDataBinding.tvBindTime.setText("未绑定"); + + } + } + }); + mViewModel.getSnInfo(); + + mViewModel.mAppInfoMutableLiveData.observe(this, new Observer() { + @Override + public void onChanged(AppInfo appInfo) { + if (appInfo != null) { + mViewDataBinding.tvUpdateVersion.setText(appInfo.getApp_version_name()); + if (ApkUtils.isUpdate(mContext, appInfo)) { + Intent intent = new Intent(mContext, UpdateActivity.class); + intent.putExtra("appInfo", appInfo); + startActivity(intent); + Toaster.show("有新的版本需要更新"); + } else { +// Toaster.show("已是最新版本"); + } + } else { + Toaster.show("已是最新版本"); + } + } + }); + mViewModel.checkUpdate(false); + } + + @Override + public void fetchData() { + Log.e(TAG, "fetchData: "); + setDeviceInfo(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + if (mClickDisposable != null && !mClickDisposable.isDisposed()) { + mClickDisposable.dispose(); + mClickDisposable = null; + } + } + + private void setDeviceInfo() { + mViewDataBinding.tvSn.setText(Utils.getSn()); + mViewDataBinding.tvImei.setText(Utils.getIMEI(mContext)); + mViewDataBinding.tvMac.setText(Utils.getMAC(mContext)); + mViewDataBinding.tvRam.setText(Math.ceil(ConvertUtils.byte2MemorySize(Utils.getTotalMem(mContext), MemoryConstants.GB)) + " GB"); + mViewDataBinding.tvAndroidVersion.setText("Android " + Build.VERSION.RELEASE); + mViewDataBinding.tvBuildVersion.setText("V" + JgyUtils.getRomVersion()); + + mViewDataBinding.tvLocalVersion.setText("V" + BuildConfig.VERSION_NAME); + + } + + public class BtnClick { + public void checkUpdate(View view) { + mViewModel.checkUpdate(true); + } + } +} diff --git a/app/src/main/java/com/fuying/sn/fragment/device/DeviceViewModel.java b/app/src/main/java/com/fuying/sn/fragment/device/DeviceViewModel.java new file mode 100644 index 0000000..f55fc89 --- /dev/null +++ b/app/src/main/java/com/fuying/sn/fragment/device/DeviceViewModel.java @@ -0,0 +1,102 @@ +package com.fuying.sn.fragment.device; + +import android.util.Log; + +import androidx.lifecycle.MutableLiveData; + +import com.fuying.sn.BuildConfig; +import com.fuying.sn.base.mvvm.BaseViewModel; +import com.fuying.sn.bean.AppInfo; +import com.fuying.sn.bean.BaseResponse; +import com.fuying.sn.bean.SnInfo; +import com.fuying.sn.databinding.FragmentDeviceBinding; +import com.fuying.sn.network.NetInterfaceManager; +import com.trello.rxlifecycle4.RxLifecycle; +import com.trello.rxlifecycle4.android.FragmentEvent; + +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.disposables.Disposable; + +public class DeviceViewModel extends BaseViewModel { + + @Override + public FragmentDeviceBinding getVDBinding() { + return binding; + } + + @Override + public void onDestroy() { + + } + + public MutableLiveData mSnInfoMutableLiveData = new MutableLiveData<>(); + + public void getSnInfo() { + NetInterfaceManager.getInstance().getSnInfoControl() + .compose(RxLifecycle.bindUntilEvent(getLifecycle(), FragmentEvent.DESTROY)) + .subscribe(new Observer>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getSnInfo", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse snInfoBaseResponse) { + Log.e("getSnInfo", "onNext: " + snInfoBaseResponse); + if (snInfoBaseResponse.code == 200) { + SnInfo snInfo = snInfoBaseResponse.data; + mSnInfoMutableLiveData.setValue(snInfo); + } else { + mSnInfoMutableLiveData.setValue(null); + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getSnInfo", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("getSnInfo", "onComplete: "); + } + }); + } + + public MutableLiveData mAppInfoMutableLiveData = new MutableLiveData<>(); + + public void checkUpdate(boolean response) { + NetInterfaceManager.getInstance().getUpdateObservable(BuildConfig.APPLICATION_ID) + .compose(RxLifecycle.bindUntilEvent(getLifecycle(), FragmentEvent.DESTROY)) + .subscribe(new Observer>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("checkUpdate", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse appInfoBaseResponse) { + Log.e("checkUpdate", "onNext: " + appInfoBaseResponse); + if (appInfoBaseResponse.code == 200) { + AppInfo appInfo = appInfoBaseResponse.data; + mAppInfoMutableLiveData.setValue(appInfo); + } else { + if (response) { + mAppInfoMutableLiveData.setValue(null); + } + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("checkUpdate", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("checkUpdate", "onComplete: "); + } + }); + } +} diff --git a/app/src/main/java/com/fuying/sn/fragment/usage/UsageFragment.java b/app/src/main/java/com/fuying/sn/fragment/usage/UsageFragment.java new file mode 100644 index 0000000..7a5fe2c --- /dev/null +++ b/app/src/main/java/com/fuying/sn/fragment/usage/UsageFragment.java @@ -0,0 +1,51 @@ +package com.fuying.sn.fragment.usage; + +import android.app.Activity; +import android.os.Bundle; + +import com.fuying.sn.R; +import com.fuying.sn.base.mvvm.fragment.BaseMvvmFragment; +import com.fuying.sn.config.CommonConfig; +import com.fuying.sn.databinding.FragmentUsageBinding; +import com.tencent.mmkv.MMKV; + +public class UsageFragment extends BaseMvvmFragment { + private static final String TAG = "UsageFragment"; + private Activity mContext; + + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + + + @Override + protected int getLayoutId() { + return R.layout.fragment_usage; + } + + @Override + protected void initDataBinding() { + mContext = getActivity(); + mViewModel.setCtx(getCtx()); + mViewModel.setLifecycle(getLifecycleSubject()); + mViewModel.setVDBinding(mViewDataBinding); + mViewDataBinding.setClick(new BtnClick()); + } + + @Override + protected void initView(Bundle bundle) { + + } + + @Override + protected void initData(Bundle savedInstanceState) { + + } + + @Override + public void fetchData() { + + } + + public class BtnClick { + + } +} diff --git a/app/src/main/java/com/fuying/sn/fragment/usage/UsageViewModel.java b/app/src/main/java/com/fuying/sn/fragment/usage/UsageViewModel.java new file mode 100644 index 0000000..5c8a28a --- /dev/null +++ b/app/src/main/java/com/fuying/sn/fragment/usage/UsageViewModel.java @@ -0,0 +1,18 @@ +package com.fuying.sn.fragment.usage; + +import com.fuying.sn.base.mvvm.BaseViewModel; +import com.fuying.sn.databinding.FragmentUsageBinding; +import com.trello.rxlifecycle4.android.FragmentEvent; + +public class UsageViewModel extends BaseViewModel { + + @Override + public FragmentUsageBinding getVDBinding() { + return binding; + } + + @Override + public void onDestroy() { + + } +} diff --git a/app/src/main/java/com/fuying/sn/manager/AmapManager.java b/app/src/main/java/com/fuying/sn/manager/AmapManager.java index 9fb5e30..b4b6ea5 100644 --- a/app/src/main/java/com/fuying/sn/manager/AmapManager.java +++ b/app/src/main/java/com/fuying/sn/manager/AmapManager.java @@ -2,29 +2,39 @@ package com.fuying.sn.manager; import android.annotation.SuppressLint; import android.content.Context; -import android.provider.Settings; +import android.text.TextUtils; import android.util.Log; -import com.baidu.location.BDAbstractLocationListener; -import com.baidu.location.BDLocation; -import com.baidu.location.LocationClient; -import com.baidu.location.LocationClientOption; -import com.fuying.sn.utils.SPUtils; +import com.amap.api.location.AMapLocation; +import com.amap.api.location.AMapLocationClient; +import com.amap.api.location.AMapLocationClientOption; +import com.amap.api.location.AMapLocationListener; +import com.fuying.sn.bean.MapBean; +import com.fuying.sn.config.CommonConfig; +import com.fuying.sn.gson.GsonUtils; +import com.fuying.sn.network.NetInterfaceManager; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.jeremyliao.liveeventbus.LiveEventBus; +import com.tencent.mmkv.MMKV; + +import java.lang.reflect.Type; public class AmapManager { private static final String TAG = "AmapManager"; + + MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + @SuppressLint("StaticFieldLeak") private static AmapManager sInstance; private Context mContext; - @SuppressLint("StaticFieldLeak") - private LocationClient mLocationClient = null; - private LocationClientOption mOption; + + private AMapLocationClient mAMapLocationClient; + private AMapLocationClientOption mAMapLocationClientOption; + private MapBean mMapBean; private AmapManager(Context context) { - this.mContext = context; -// Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps"); - Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+network"); - Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ASSISTED_GPS_ENABLED, 1); + this.mContext = context.getApplicationContext(); initAmap(); } @@ -41,161 +51,124 @@ public class AmapManager { if (sInstance == null) { throw new IllegalStateException("You must be init AmapManager first"); } + return sInstance; } + private AMapLocationClientOption getDefaultOption() { + if (mAMapLocationClientOption == null) { + mAMapLocationClientOption = new AMapLocationClientOption(); + } + mAMapLocationClientOption.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.SignIn); + //设置定位模式为AMapLocationMode.Hight_Accuracy,高精度模式。 + mAMapLocationClientOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); + mAMapLocationClientOption.setNeedAddress(true); + //获取一次定位结果: + //该方法默认为false。 + mAMapLocationClientOption.setOnceLocation(true); + //获取最近3s内精度最高的一次定位结果: + //设置setOnceLocationLatest(boolean b)接口为true,启动定位时SDK会返回最近3s内精度最高的一次定位结果。 + // 如果设置其为true,setOnceLocation(boolean b)接口也会被设置为true,反之不会,默认为false。 + mAMapLocationClientOption.setOnceLocationLatest(true); + return mAMapLocationClientOption; + } + public void initAmap() { - if (mLocationClient == null) { - mLocationClient = new LocationClient(mContext); + if (mAMapLocationClient == null) { + mAMapLocationClient = new AMapLocationClient(mContext); } -// Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps"); - Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+network"); - Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ASSISTED_GPS_ENABLED, 1); - mLocationClient.setLocOption(getDefaultLocationClientOption()); - mLocationClient.registerLocationListener(mListener); - mLocationClient.stop(); - mLocationClient.start(); + mAMapLocationClient.setLocationOption(getDefaultOption()); + + //设置定位监听 + mAMapLocationClient.setLocationListener(mAMapLocationListener); + //设置场景模式后最好调用一次stop,再调用start以保证场景模式生效 + + startLocation(); + + String jsonString = mMMKV.decodeString(CommonConfig.MAP_LOCATION_JSON_KEY, ""); + if (!TextUtils.isEmpty(jsonString)) { + Gson gson = new Gson(); + Type type = new TypeToken() { + }.getType(); + mMapBean = gson.fromJson(jsonString, type); + } else { + Log.e(TAG, "initAmap: jsonString is empty"); + } + } - public LocationClient getLocationClient() { - if (mLocationClient == null) { - initAmap(); - } - return mLocationClient; + public void startLocation() { + mAMapLocationClient.stopLocation(); + mAMapLocationClient.startLocation(); + Log.e(TAG, "initAmap: " + "startLocation"); } - /*** - * - * @return DefaultLocationClientOption 默认O设置 - */ - public LocationClientOption getDefaultLocationClientOption() { - if (mOption == null) { - mOption = new LocationClientOption(); - mOption.setCoorType("bd09ll"); // 可选,默认gcj02,设置返回的定位结果坐标系,如果配合百度地图使用,建议设置为bd09ll; - mOption.setScanSpan(0); // 可选,默认0,即仅定位一次,设置发起连续定位请求的间隔需要大于等于1000ms才是有效的 - mOption.setIsNeedAddress(true); // 可选,设置是否需要地址信息,默认不需要 - mOption.setIsNeedLocationDescribe(true); // 可选,设置是否需要地址描述 - mOption.setNeedDeviceDirect(false); // 可选,设置是否需要设备方向结果 - mOption.setLocationNotify(false); // 可选,默认false,设置是否当gps有效时按照1S1次频率输出GPS结果 - mOption.setIgnoreKillProcess(true); // 可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop - mOption.setIsNeedLocationDescribe(true); // 可选,默认false,设置是否需要位置语义化结果,可以在BDLocation - mOption.setIsNeedLocationPoiList(true); // 可选,默认false,设置是否需要POI结果,可以在BDLocation - mOption.SetIgnoreCacheException(false); // 可选,默认false,设置是否收集CRASH信息,默认收集 - mOption.setLocationMode(LocationClientOption.LocationMode.Battery_Saving); // 可选,默认高精度,设置定位模式,高精度,低功耗,仅设备,模糊 - mOption.setIsNeedAltitude(false); // 可选,默认false,设置定位时是否需要海拔信息,默认不需要,除基础定位版本都可用 - // 可选,设置首次定位时选择定位速度优先还是定位准确性优先,默认为速度优先 -// mOption.setFirstLocType(LocationClientOption.FirstLocType.SPEED_IN_FIRST_LOC); - } - return mOption; - } - - - /***** - * - * 定位结果回调,重写onReceiveLocation方法,可以直接拷贝如下代码到自己工程中修改 - * - */ - private BDAbstractLocationListener mListener = new BDAbstractLocationListener() { - - /** - * 定位请求回调函数 - * @param location 定位结果 - */ + private AMapLocationListener mAMapLocationListener = new AMapLocationListener() { @Override - public void onReceiveLocation(BDLocation location) { - if (null != location) { - switch (location.getLocType()) { - case BDLocation.TypeGpsLocation:// GPS定位结果 - case BDLocation.TypeNetWorkLocation:// 网络定位结果 - case BDLocation.TypeOffLineLocation:// 离线定位结果 - Log.e(TAG, "onLocationChanged: " + "定位成功"); - Log.e(TAG, "onLocationChanged: " + location.getAddrStr() + location.getLocationDescribe()); - SPUtils.put(mContext, "AmapAddress", location.getAddrStr() + location.getLocationDescribe()); - SPUtils.put(mContext, "longitude", location.getLongitude()); - SPUtils.put(mContext, "latitude", location.getLatitude()); - SPUtils.put(mContext, "AmapError", "-"); - break; - case BDLocation.TypeServerError: - Log.e(TAG, "onReceiveLocation: " + "服务端网络定位失败"); - SPUtils.put(mContext, "AmapError", "服务端网络定位失败,可以反馈IMEI号和大体定位时间到loc-bugs@baidu.com,会有人追查原因"); - break; - case BDLocation.TypeNetWorkException: - Log.e(TAG, "onReceiveLocation: " + "网络不同导致定位失败,请检查网络是否通畅"); - SPUtils.put(mContext, "AmapError", "网络不同导致定位失败,请检查网络是否通畅"); - break; - case BDLocation.TypeCriteriaException: - Log.e(TAG, "onReceiveLocation: " + "无法获取有效定位依据导致定位失败"); - SPUtils.put(mContext, "AmapError", "无法获取有效定位依据导致定位失败,一般是由于手机的原因,处于飞行模式下一般会造成这种结果,可以试着重启手机"); - break; - default: - } + public void onLocationChanged(AMapLocation aMapLocation) { + StringBuilder sb = new StringBuilder(); + //errCode等于0代表定位成功,其他的为定位失败,具体的可以参照官网定位错误码说明 + if (aMapLocation.getErrorCode() == 0) { + Log.e(TAG, "onLocationChanged: " + "定位成功"); + updateAddress(aMapLocation); + + mMapBean = getMapBean(aMapLocation); + saveMapResult(mMapBean); + LiveEventBus.get(CommonConfig.MAP_BEAN) + .post(mMapBean); + LiveEventBus.get(CommonConfig.MAP_ADDRESS_KEY) + .post(mMapBean.getAddress()); + + Log.e(TAG, "onLocationChanged: " + aMapLocation.getAddress()); + sb.append(aMapLocation.getAddress()).append("\n"); + mMMKV.encode(CommonConfig.MAP_onLocationChanged_time_KEY, System.currentTimeMillis()); + } else { + //定位失败 + sb.append("定位失败" + "\n"); + sb.append(aMapLocation.getErrorInfo()); + mMMKV.encode(CommonConfig.MAP_ERROR_KEY, aMapLocation.getErrorInfo()); + Log.e(TAG, "onLocationChanged: " + "定位失败"); } - Log.e(TAG, "AmapAddress: " + SPUtils.get(mContext, "AmapAddress", "-")); - Log.e(TAG, "AmapError: " + SPUtils.get(mContext, "AmapError", "-")); - Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-gps"); - Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-network"); - Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, ""); - Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ASSISTED_GPS_ENABLED, 0); - mLocationClient.stop(); - } - - @Override - public void onConnectHotSpotMessage(String s, int i) { - super.onConnectHotSpotMessage(s, i); - } - - /** - * 回调定位诊断信息,开发者可以根据相关信息解决定位遇到的一些问题 - * @param locType 当前定位类型 - * @param diagnosticType 诊断类型(1~9) - * @param diagnosticMessage 具体的诊断信息释义 - */ - @Override - public void onLocDiagnosticMessage(int locType, int diagnosticType, String diagnosticMessage) { - super.onLocDiagnosticMessage(locType, diagnosticType, diagnosticMessage); -// int tag = 2; - StringBuffer sb = new StringBuffer(256); - sb.append("诊断结果: "); - if (locType == BDLocation.TypeNetWorkLocation) { - if (diagnosticType == 1) { - sb.append("网络定位成功,没有开启GPS,建议打开GPS会更好"); - sb.append("\n" + diagnosticMessage); - } else if (diagnosticType == 2) { - sb.append("网络定位成功,没有开启Wi-Fi,建议打开Wi-Fi会更好"); - sb.append("\n" + diagnosticMessage); - } - } else if (locType == BDLocation.TypeOffLineLocationFail) { - if (diagnosticType == 3) { - sb.append("定位失败,请您检查您的网络状态"); - sb.append("\n" + diagnosticMessage); - } - } else if (locType == BDLocation.TypeCriteriaException) { - if (diagnosticType == 4) { - sb.append("定位失败,无法获取任何有效定位依据"); - sb.append("\n" + diagnosticMessage); - } else if (diagnosticType == 5) { - sb.append("定位失败,无法获取有效定位依据,请检查运营商网络或者Wi-Fi网络是否正常开启,尝试重新请求定位"); - sb.append(diagnosticMessage); - } else if (diagnosticType == 6) { - sb.append("定位失败,无法获取有效定位依据,请尝试插入一张sim卡或打开Wi-Fi重试"); - sb.append("\n" + diagnosticMessage); - } else if (diagnosticType == 7) { - sb.append("定位失败,飞行模式下无法获取有效定位依据,请关闭飞行模式重试"); - sb.append("\n" + diagnosticMessage); - } else if (diagnosticType == 9) { - sb.append("定位失败,无法获取任何有效定位依据"); - sb.append("\n" + diagnosticMessage); - } - } else if (locType == BDLocation.TypeServerError) { - if (diagnosticType == 8) { - sb.append("定位失败,请确认您定位的开关打开状态,是否赋予APP定位权限"); - sb.append("\n" + diagnosticMessage); - } - } - Log.e(TAG, "onLocationChanged: " + "定位失败"); - SPUtils.put(mContext, "AmapError", sb); - Log.e(TAG, "onLocDiagnosticMessage: " + sb); - mLocationClient.stop(); + Log.e(TAG, "amap: " + sb.toString()); } }; + + private void updateAddress(AMapLocation aMapLocation) { + NetInterfaceManager.getInstance().updateAdminInfo(); + } + + private MapBean getMapBean(AMapLocation location) { + MapBean mapBean = new MapBean(); + mapBean.setLongitude(location.getLongitude()); + mapBean.setLatitude(location.getLatitude()); + mapBean.setAdcode(location.getAdCode()); + mapBean.setAddress(location.getAddress()); + mapBean.setCity(location.getCity()); + mapBean.setCityCode(location.getCityCode()); + mapBean.setCountry(location.getCountry()); + mapBean.setCountryCode(location.getAdCode()); + mapBean.setDistrict(location.getDistrict()); + mapBean.setProvince(location.getProvince()); + mapBean.setStreet(location.getStreet()); + mapBean.setStreetNumber(location.getStreetNum()); + mapBean.setTown(location.getStreet()); + mapBean.setLocationDescribe(location.getLocationDetail()); + Log.e(TAG, "getMapBean: " + GsonUtils.toJSONString(mapBean)); + return mapBean; + + } + + private void saveMapResult(MapBean mapBean) { + Log.e(TAG, "saveMapResult: " + GsonUtils.toJSONString(mapBean)); + mMMKV.encode(CommonConfig.MAP_LOCATION_JSON_KEY, GsonUtils.toJSONString(mapBean)); + mMMKV.encode(CommonConfig.MAP_LONGITUDE_KEY, mapBean.getLongitude()); + mMMKV.encode(CommonConfig.MAP_LATITUDE_KEY, mapBean.getLatitude()); + mMMKV.encode(CommonConfig.MAP_ADDRESS_KEY, mapBean.getAddress()); + mMMKV.encode(CommonConfig.MAP_PROVINCE_KEY, mapBean.getProvince()); + mMMKV.encode(CommonConfig.MAP_CITY_KEY, mapBean.getCity()); + mMMKV.encode(CommonConfig.MAP_DISTRICT_KEY, mapBean.getDistrict()); + mMMKV.encode(CommonConfig.MAP_STREET_KEY, mapBean.getStreet()); + mMMKV.encode(CommonConfig.MAP_LOCATION_DESCRIBE_KEY, mapBean.getLocationDescribe()); + } + } diff --git a/app/src/main/java/com/fuying/sn/manager/ControlManager.java b/app/src/main/java/com/fuying/sn/manager/ControlManager.java index 8865476..5e9e158 100644 --- a/app/src/main/java/com/fuying/sn/manager/ControlManager.java +++ b/app/src/main/java/com/fuying/sn/manager/ControlManager.java @@ -14,7 +14,7 @@ import com.fuying.sn.bean.SystemSettings; import com.fuying.sn.config.CommonConfig; import com.fuying.sn.gson.GsonUtils; import com.fuying.sn.utils.ApkUtils; -import com.fuying.sn.utils.JGYUtils; +import com.fuying.sn.utils.JgyUtils; import com.fuying.sn.utils.SPUtils; import com.fuying.sn.utils.ToastUtil; import com.google.gson.JsonObject; @@ -87,7 +87,7 @@ public class ControlManager { setAppstoreAdmin(systemSettings); setDefaultApp(systemSettings); setIsControl(systemSettings); - JGYUtils.getInstance().updateForbidList(); + JgyUtils.getInstance().updateForbidList(); } } @@ -117,7 +117,7 @@ public class ControlManager { setAppstoreAdmin(systemSettings); setDefaultApp(systemSettings); setIsControl(systemSettings); - JGYUtils.getInstance().updateForbidList(); + JgyUtils.getInstance().updateForbidList(); } /** @@ -202,7 +202,7 @@ public class ControlManager { break; } Intent usbIntent = new Intent(usbStatus); - if (JGYUtils.getInstance().checkAppPlatform() != JGYUtils.G11JPlatform) { + if (JgyUtils.getInstance().checkAppPlatform() != JgyUtils.G11JPlatform) { usbIntent.setPackage("com.android.settings"); } // if (!BuildConfig.DEBUG) @@ -246,7 +246,7 @@ public class ControlManager { boolean aole_white_list_Array = Settings.System.putString(mResolver, CommonConfig.AOLE_ACTION_WHITE_LIST_ARRAY, setting_phones); Log.e("SystemSetting", "aole_white_list_Array: " + aole_white_list_Array + "=" + setting_phones); - if (JGYUtils.getInstance().checkAppPlatform() == JGYUtils.M40sePlatform) { + if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.M40sePlatform) { Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_SDCARD_FORBID_ON, 0); } else { int setting_memory = changeNum(settings.getSetting_memory()); @@ -268,7 +268,7 @@ public class ControlManager { boolean aole_white_list_Array = Settings.System.putString(mResolver, CommonConfig.AOLE_ACTION_WHITE_LIST_ARRAY, ""); // ToastTool.show("qch_call_forbid::"+setting_call+"----setting_phones::"+setting_phones+"----"+aole_white_list_Array+"---"+qch_call_forbid); Log.e(TAG, "aole_white_list_Array:" + aole_white_list_Array + "---" + aole_white_list_Array); - if (JGYUtils.getInstance().checkAppPlatform() == JGYUtils.M40sePlatform) { + if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.M40sePlatform) { //在m40se上 开启管控会造成第三方app无法读取sd卡,暂时打开 Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_SDCARD_FORBID_ON, 0); } else { @@ -395,7 +395,7 @@ public class ControlManager { break; default: } - if (JGYUtils.getInstance().checkAppPlatform() == JGYUtils.T30ProPlatform) { + if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.T30ProPlatform) { Intent navIntent = new Intent(navigationStatus); mContext.sendBroadcast(navIntent); } else { @@ -836,7 +836,7 @@ public class ControlManager { Log.e(TAG, "setDefaultApp: desktop_app = " + desktop_app); if (!TextUtils.isEmpty(desktop_app)) { mMMKV.encode(CommonConfig.DESKTOP_APP_KEY, desktop_app); - JGYUtils.getInstance().setDefaultDesktop(desktop_app); + JgyUtils.getInstance().setDefaultDesktop(desktop_app); } else { mMMKV.encode(CommonConfig.DESKTOP_APP_KEY, ""); } @@ -844,7 +844,7 @@ public class ControlManager { Log.e(TAG, "setDefaultApp: browser_app = " + browser_app); if (!TextUtils.isEmpty(browser_app)) { mMMKV.encode(CommonConfig.BROWSER_APP_KEY, browser_app); - JGYUtils.getInstance().setDefaultBrowser(browser_app); + JgyUtils.getInstance().setDefaultBrowser(browser_app); } else { mMMKV.encode(CommonConfig.BROWSER_APP_KEY, ""); } @@ -852,7 +852,7 @@ public class ControlManager { Log.e(TAG, "setDefaultApp: typewriting_app = " + typewriting_app); if (!TextUtils.isEmpty(typewriting_app)) { mMMKV.encode(CommonConfig.TYPEWRITING_APP_KEY, typewriting_app); - JGYUtils.getInstance().setDefaultInputMethod(typewriting_app); + JgyUtils.getInstance().setDefaultInputMethod(typewriting_app); } else { mMMKV.encode(CommonConfig.TYPEWRITING_APP_KEY, ""); } @@ -865,17 +865,17 @@ public class ControlManager { String desktop_app = mMMKV.decodeString(CommonConfig.DESKTOP_APP_KEY, ""); Log.e(TAG, "setDefaultApp: desktop_app = " + desktop_app); if (!TextUtils.isEmpty(desktop_app)) { - JGYUtils.getInstance().setDefaultDesktop(desktop_app); + JgyUtils.getInstance().setDefaultDesktop(desktop_app); } String browser_app = mMMKV.decodeString(CommonConfig.BROWSER_APP_KEY, ""); Log.e(TAG, "setDefaultApp: browser_app = " + browser_app); if (!TextUtils.isEmpty(browser_app)) { - JGYUtils.getInstance().setDefaultBrowser(browser_app); + JgyUtils.getInstance().setDefaultBrowser(browser_app); } String typewriting_app = mMMKV.decodeString(CommonConfig.TYPEWRITING_APP_KEY, ""); Log.e(TAG, "setDefaultApp: typewriting_app = " + typewriting_app); if (!TextUtils.isEmpty(typewriting_app)) { - JGYUtils.getInstance().setDefaultInputMethod(typewriting_app); + JgyUtils.getInstance().setDefaultInputMethod(typewriting_app); } } diff --git a/app/src/main/java/com/fuying/sn/network/NetInterfaceManager.java b/app/src/main/java/com/fuying/sn/network/NetInterfaceManager.java index 6ab1d44..c0d3f23 100644 --- a/app/src/main/java/com/fuying/sn/network/NetInterfaceManager.java +++ b/app/src/main/java/com/fuying/sn/network/NetInterfaceManager.java @@ -81,10 +81,10 @@ import com.fuying.sn.network.api.QueryAllApp; import com.fuying.sn.network.api.QueryAppInside; import com.fuying.sn.network.api.QuerySnAppStart; import com.fuying.sn.network.api.RunningApp; -import com.fuying.sn.network.api.SNInfoApi; import com.fuying.sn.network.api.ScreenLock; import com.fuying.sn.network.api.ScreenState; import com.fuying.sn.network.api.Setting; +import com.fuying.sn.network.api.SnApi; import com.fuying.sn.network.api.SnBindApi; import com.fuying.sn.network.api.SnTagApi; import com.fuying.sn.network.api.TimeControl; @@ -98,7 +98,7 @@ import com.fuying.sn.utils.ApkUtils; import com.fuying.sn.utils.AppUsedTimeUtils; import com.fuying.sn.utils.CmdUtil; import com.fuying.sn.utils.FileUtils; -import com.fuying.sn.utils.JGYUtils; +import com.fuying.sn.utils.JgyUtils; import com.fuying.sn.utils.SPUtils; import com.fuying.sn.utils.StringUtils; import com.fuying.sn.utils.URLUtils; @@ -107,8 +107,6 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; -import com.tencent.android.tpush.XGIOperateCallback; -import com.tencent.android.tpush.XGPushManager; import com.tencent.mmkv.MMKV; import com.trello.rxlifecycle4.RxLifecycle; import com.trello.rxlifecycle4.android.ActivityEvent; @@ -246,14 +244,14 @@ public class NetInterfaceManager { * * */ - public Observable> getsnInfoControl() { - return mRetrofit.create(SNInfoApi.class) + public Observable> getSnInfoControl() { + return mRetrofit.create(SnApi.class) .getsninfo(Utils.getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } - public Observable> getsettingControl() { + public Observable> getSettingControl() { return mRetrofit.create(Setting.class) .getSetting(Utils.getSerial()) .subscribeOn(Schedulers.io()) @@ -353,13 +351,13 @@ public class NetInterfaceManager { public Observable> getUpdateObservable(String packageName) { return getNewestAppUpdateControl() - .getAppUpdate(packageName, "0", JGYUtils.getInstance().checkAppPlatform()) + .getAppUpdate(packageName, "0", JgyUtils.getInstance().checkAppPlatform()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable>> getOverallAppObservable() { - int platformCode = JGYUtils.getInstance().checkAppPlatform(); + int platformCode = JgyUtils.getInstance().checkAppPlatform(); return getOverallAppByPlatformControl() .getOverallApp(platformCode) .subscribeOn(Schedulers.io()) @@ -604,10 +602,10 @@ public class NetInterfaceManager { if (refresh) { connectMode = ConnectMode.DEFAULT; } - if (ConnectManager.getInstance().isNeedConnect(UrlAddress.SNINFO, connectMode)) { + if (ConnectManager.getInstance().isNeedConnect(UrlAddress.SN_INFO, connectMode)) { getSnInfo(lifecycle, callback); } else { - String jsonString = mCacheHelper.getAsString(UrlAddress.SNINFO); + String jsonString = mCacheHelper.getAsString(UrlAddress.SN_INFO); //为 "" 是已经请求成功的 if (jsonString == null) { getSnInfo(lifecycle, callback); @@ -623,18 +621,18 @@ public class NetInterfaceManager { } public void getSnInfo(BehaviorSubject lifecycle, ObserverCallback callback) { - getsnInfoControl() + getSnInfoControl() .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) .subscribe(getSnInfoObserver(callback)); } public void getSnInfo(ObserverCallback callback) { - getsnInfoControl() + getSnInfoControl() .subscribe(getSnInfoObserver(callback)); } public void getSnInfo() { - getsnInfoControl() + getSnInfoControl() .subscribe(getSnInfoObserver(null)); } @@ -653,7 +651,7 @@ public class NetInterfaceManager { SPUtils.put(mContext, CommonConfig.JGY_FIRST_CONNECT, 1); if (callback != null) callback.onNext(userInfoBaseResponse); - mCacheHelper.put(UrlAddress.SNINFO, GsonUtils.toJSONString(userInfoBaseResponse)); + mCacheHelper.put(UrlAddress.SN_INFO, GsonUtils.toJSONString(userInfoBaseResponse)); int code = userInfoBaseResponse.code; if (userInfoBaseResponse.code == 200) { SPUtils.put(mContext, CommonConfig.isLogined, 1); @@ -671,11 +669,11 @@ public class NetInterfaceManager { SPUtils.put(mContext, "USERINFO_GRADE", snInfo.getGrade()); } } else if (code == 300) { - mCacheHelper.put(UrlAddress.SNINFO, ""); + mCacheHelper.put(UrlAddress.SN_INFO, ""); SPUtils.put(mContext, CommonConfig.isLogined, 0); Settings.System.putInt(mContext.getContentResolver(), CommonConfig.KEY_IS_CONTROL, 0); } else if (code == 401) { - mCacheHelper.put(UrlAddress.SNINFO, ""); + mCacheHelper.put(UrlAddress.SN_INFO, ""); SPUtils.put(mContext, CommonConfig.isLogined, 2); Settings.System.putInt(mContext.getContentResolver(), CommonConfig.KEY_IS_CONTROL, 0); } @@ -704,27 +702,27 @@ public class NetInterfaceManager { */ public void setPushTags() { Set set = new HashSet<>(); - JGYUtils.getInstance().getAppPlatform(platform -> { - if (platform == JGYUtils.MTKPlatform) { - set.add(JGYUtils.MTKTag); - } else if (platform == JGYUtils.ZhanruiPlatform) { - set.add(JGYUtils.ZhanruiTag); - } else if (platform == JGYUtils.M40sePlatform) { - set.add(JGYUtils.M40SETag); - } else if (platform == JGYUtils.T30ProPlatform) { - set.add(JGYUtils.T30PROTag); - } else if (platform == JGYUtils.MTK8515Platform) { - set.add(JGYUtils.MTK8515Tag); - } else if (platform == JGYUtils.G13Platform) { - set.add(JGYUtils.G13Tag); - } else if (platform == JGYUtils.iPlay50SEPlatform) { - set.add(JGYUtils.iPlay50SETag); - } else if (platform == JGYUtils.G6Platform) { - set.add(JGYUtils.G6Tag); - } else if (platform == JGYUtils.G11JPlatform) { - set.add(JGYUtils.G11JTag); - } else if (platform == JGYUtils.G12NLPlatform) { - set.add(JGYUtils.G12NLTag); + JgyUtils.getInstance().getAppPlatform(platform -> { + if (platform == JgyUtils.MTKPlatform) { + set.add(JgyUtils.MTKTag); + } else if (platform == JgyUtils.ZhanruiPlatform) { + set.add(JgyUtils.ZhanruiTag); + } else if (platform == JgyUtils.M40sePlatform) { + set.add(JgyUtils.M40SETag); + } else if (platform == JgyUtils.T30ProPlatform) { + set.add(JgyUtils.T30PROTag); + } else if (platform == JgyUtils.MTK8515Platform) { + set.add(JgyUtils.MTK8515Tag); + } else if (platform == JgyUtils.G13Platform) { + set.add(JgyUtils.G13Tag); + } else if (platform == JgyUtils.iPlay50SEPlatform) { + set.add(JgyUtils.iPlay50SETag); + } else if (platform == JgyUtils.G6Platform) { + set.add(JgyUtils.G6Tag); + } else if (platform == JgyUtils.G11JPlatform) { + set.add(JgyUtils.G11JTag); + } else if (platform == JgyUtils.G12NLPlatform) { + set.add(JgyUtils.G12NLTag); } }); clearAndAppendTags(set); @@ -733,38 +731,27 @@ public class NetInterfaceManager { public void setPushTags(String tag) { Set set = new HashSet<>(); set.add(tag); - JGYUtils.getInstance().getAppPlatform(platform -> { - if (platform == JGYUtils.MTKPlatform) { - set.add(JGYUtils.MTKTag); - } else if (platform == JGYUtils.ZhanruiPlatform) { - set.add(JGYUtils.ZhanruiTag); - } else if (platform == JGYUtils.M40sePlatform) { - set.add(JGYUtils.M40SETag); - } else if (platform == JGYUtils.T30ProPlatform) { - set.add(JGYUtils.T30PROTag); - } else if (platform == JGYUtils.MTK8515Platform) { - set.add(JGYUtils.MTK8515Tag); - } else if (platform == JGYUtils.G13Platform) { - set.add(JGYUtils.G13Tag); - } else if (platform == JGYUtils.iPlay50SEPlatform) { - set.add(JGYUtils.iPlay50SETag); - } else if (platform == JGYUtils.G6Platform) { - set.add(JGYUtils.G6Tag); - } else if (platform == JGYUtils.G11JPlatform) { - set.add(JGYUtils.G11JTag); - } else if (platform == JGYUtils.G12NLPlatform) { - set.add(JGYUtils.G12NLTag); - } - }); - XGPushManager.clearAndAppendTags(mContext, "clearAndAppendTags :" + System.currentTimeMillis(), set, new XGIOperateCallback() { - @Override - public void onSuccess(Object o, int i) { - Log.e("clearAndAppendTags", "onSuccess: " + o + " tag " + set); - } - - @Override - public void onFail(Object o, int i, String s) { - Log.e("clearAndAppendTags", "onFail: " + o); + JgyUtils.getInstance().getAppPlatform(platform -> { + if (platform == JgyUtils.MTKPlatform) { + set.add(JgyUtils.MTKTag); + } else if (platform == JgyUtils.ZhanruiPlatform) { + set.add(JgyUtils.ZhanruiTag); + } else if (platform == JgyUtils.M40sePlatform) { + set.add(JgyUtils.M40SETag); + } else if (platform == JgyUtils.T30ProPlatform) { + set.add(JgyUtils.T30PROTag); + } else if (platform == JgyUtils.MTK8515Platform) { + set.add(JgyUtils.MTK8515Tag); + } else if (platform == JgyUtils.G13Platform) { + set.add(JgyUtils.G13Tag); + } else if (platform == JgyUtils.iPlay50SEPlatform) { + set.add(JgyUtils.iPlay50SETag); + } else if (platform == JgyUtils.G6Platform) { + set.add(JgyUtils.G6Tag); + } else if (platform == JgyUtils.G11JPlatform) { + set.add(JgyUtils.G11JTag); + } else if (platform == JgyUtils.G12NLPlatform) { + set.add(JgyUtils.G12NLTag); } }); @@ -792,17 +779,6 @@ public class NetInterfaceManager { if (!TextUtils.isEmpty(tag)) { tagSets.add(tag); } - XGPushManager.clearAndAppendTags(mContext, "clearAndAppendTags :" + System.currentTimeMillis(), tagSets, new XGIOperateCallback() { - @Override - public void onSuccess(Object o, int i) { - Log.e("clearAndAppendTags", "onSuccess: " + o + " tag " + tagSets); - } - - @Override - public void onFail(Object o, int i, String s) { - Log.e("clearAndAppendTags", "onFail: " + o); - } - }); String[] set = new ArrayList<>(tagSets).toArray(new String[tagSets.size()]); CloudPushService pushService = PushServiceFactory.getCloudPushService(); @@ -836,8 +812,8 @@ public class NetInterfaceManager { private Set getShowPackages() { HashSet pkgSet = new HashSet<>(); pkgSet.addAll(showPackages); - pkgSet.addAll(JGYUtils.getInstance().getFXYApp()); - pkgSet.addAll(JGYUtils.getInstance().getAppAndWhite()); + pkgSet.addAll(JgyUtils.getInstance().getFXYApp()); + pkgSet.addAll(JgyUtils.getInstance().getAppAndWhite()); return pkgSet; } @@ -946,8 +922,8 @@ public class NetInterfaceManager { } public void getElderlyUsersApp() { - Observable.zip(getUpdateObservable(JGYUtils.AIHealth), - getUpdateObservable(JGYUtils.ElderlyDesktop), + Observable.zip(getUpdateObservable(JgyUtils.AIHealth), + getUpdateObservable(JgyUtils.ElderlyDesktop), new BiFunction, BaseResponse, List>() { @Override public List apply(BaseResponse appInfoBaseResponse, BaseResponse appInfoBaseResponse2) throws Throwable { @@ -992,7 +968,7 @@ public class NetInterfaceManager { public void checkUpdate(String packageName, String versionCode) { Log.e("checkUpdate", "packageName: " + packageName); getNewestAppUpdateControl() - .getAppUpdate(packageName, versionCode, JGYUtils.getInstance().checkAppPlatform()) + .getAppUpdate(packageName, versionCode, JgyUtils.getInstance().checkAppPlatform()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer>() { @@ -1035,10 +1011,10 @@ public class NetInterfaceManager { if (refresh) { connectMode = ConnectMode.DEFAULT; } - if (ConnectManager.getInstance().isNeedConnect(UrlAddress.GET_NEWESTAPPUPDATE, connectMode)) { + if (ConnectManager.getInstance().isNeedConnect(UrlAddress.GET_NEWEST_APPUPDATE, connectMode)) { checkAllAppUpdate(lifecycle, callback); } else { - String jsonString = mCacheHelper.getAsString(UrlAddress.GET_NEWESTAPPUPDATE); + String jsonString = mCacheHelper.getAsString(UrlAddress.GET_NEWEST_APPUPDATE); //为 "" 是已经请求成功的 if (jsonString == null) { checkAllAppUpdate(lifecycle, callback); @@ -1056,7 +1032,7 @@ public class NetInterfaceManager { public void checkAllAppUpdate(BehaviorSubject lifecycle, CompleteCallback callback) { Observable.zip( getUpdateObservable(BuildConfig.APPLICATION_ID), - getUpdateObservable(JGYUtils.PACKAGE_APPSTORE), + getUpdateObservable(JgyUtils.PACKAGE_APPSTORE), // getUpdateObservable(JGYUtils.PACKAGE_OS), // getUpdateObservable(JGYUtils.PACKAGE_BROWSER), // getUpdateObservable(JGYUtils.Notifications), @@ -1091,7 +1067,7 @@ public class NetInterfaceManager { @Override public void onNext(@NonNull List appInfos) { Log.e("checkAllAppUpdate", "onNext: " + appInfos); - mCacheHelper.put(UrlAddress.GET_NEWESTAPPUPDATE, GsonUtils.toJSONString(appInfos)); + mCacheHelper.put(UrlAddress.GET_NEWEST_APPUPDATE, GsonUtils.toJSONString(appInfos)); getAllAppUpdate(appInfos); } @@ -1114,11 +1090,11 @@ public class NetInterfaceManager { if (refresh) { connectMode = ConnectMode.DEFAULT; } - if (ConnectManager.getInstance().isNeedConnect(JGYUtils.FUXIAOYING_KEY, connectMode)) { + if (ConnectManager.getInstance().isNeedConnect(JgyUtils.FUXIAOYING_KEY, connectMode)) { checkFXYAppUpdate(lifecycle, callback); } else { //有乱码 - String jsonString = mMMKV.decodeString(JGYUtils.FUXIAOYING_KEY + "_mmkv"); + String jsonString = mMMKV.decodeString(JgyUtils.FUXIAOYING_KEY + "_mmkv"); Log.e(TAG, "checkFXYAppUpdate: jsonString = " + jsonString); //为 "" 是已经请求成功的 if (jsonString == null) { @@ -1136,15 +1112,15 @@ public class NetInterfaceManager { public void checkFXYAppUpdate(BehaviorSubject lifecycle, CompleteCallback callback) { Observable.zip( - getUpdateObservable(JGYUtils.gkwxhd), - getUpdateObservable(JGYUtils.fuxiaoying), - getUpdateObservable(JGYUtils.moshujia), - getUpdateObservable(JGYUtils.english), - getUpdateObservable(JGYUtils.zhiduoke), - getUpdateObservable(JGYUtils.aobama), - getUpdateObservable(JGYUtils.growthspace), - getUpdateObservable(JGYUtils.pandaabc), - getUpdateObservable(JGYUtils.qibenyi), + getUpdateObservable(JgyUtils.gkwxhd), + getUpdateObservable(JgyUtils.fuxiaoying), + getUpdateObservable(JgyUtils.moshujia), + getUpdateObservable(JgyUtils.english), + getUpdateObservable(JgyUtils.zhiduoke), + getUpdateObservable(JgyUtils.aobama), + getUpdateObservable(JgyUtils.growthspace), + getUpdateObservable(JgyUtils.pandaabc), + getUpdateObservable(JgyUtils.qibenyi), (appInfoBaseResponse, appInfoBaseResponse2, appInfoBaseResponse3, appInfoBaseResponse4, appInfoBaseResponse5, appInfoBaseResponse6, appInfoBaseResponse7, appInfoBaseResponse8, appInfoBaseResponse9) -> { List appInfoList = new ArrayList<>(); if (appInfoBaseResponse.code == 200) { @@ -1188,7 +1164,7 @@ public class NetInterfaceManager { @Override public void onNext(@NonNull List appInfos) { Log.e("checkFXYAppUpdate", "onNext: " + appInfos); - mCacheHelper.put(JGYUtils.FUXIAOYING_KEY, GsonUtils.toJSONString(appInfos)); + mCacheHelper.put(JgyUtils.FUXIAOYING_KEY, GsonUtils.toJSONString(appInfos)); getAllAppUpdate(appInfos); } @@ -1839,7 +1815,7 @@ public class NetInterfaceManager { } String jsonString = GsonUtils.toJSONString(hideAPPList); SPUtils.put(mContext, "Hide_APP_List", String.join(",", jsonString)); - JGYUtils.getInstance().updateHideList(); + JgyUtils.getInstance().updateHideList(); Log.e(TAG, "Hide_APP_List: " + jsonString); } } @@ -1890,16 +1866,17 @@ public class NetInterfaceManager { } public void updateAdminInfo() { - String address = String.valueOf(SPUtils.get(mContext, "AmapAddress", "-")); - String longitude = String.valueOf(SPUtils.get(mContext, "longitude", "0")); - String latitude = String.valueOf(SPUtils.get(mContext, "latitude", "0")); + String address = String.valueOf(mMMKV.decodeString(CommonConfig.MAP_ADDRESS_KEY, "-")); + String longitude = String.valueOf(mMMKV.decodeDouble(CommonConfig.MAP_LONGITUDE_KEY, 0L)); + String latitude = String.valueOf(mMMKV.decodeDouble(CommonConfig.MAP_LATITUDE_KEY, 0L)); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("address", address); jsonObject.addProperty("longitude", longitude); jsonObject.addProperty("latitude", latitude); + JsonObject softwareJson = new JsonObject(); - softwareJson.addProperty("appstore_version", ApkUtils.getAPPVersionName(mContext, JGYUtils.PACKAGE_APPSTORE)); - softwareJson.addProperty("updatetools_version", ApkUtils.getAPPVersionName(mContext, JGYUtils.PACKAGE_UPDATETOOLS)); + softwareJson.addProperty("appstore_version", ApkUtils.getAPPVersionName(mContext, JgyUtils.PACKAGE_APPSTORE)); + softwareJson.addProperty("updatetools_version", ApkUtils.getAPPVersionName(mContext, JgyUtils.PACKAGE_UPDATETOOLS)); softwareJson.addProperty("info_version", ApkUtils.getAPPVersionName(mContext, "com.fuying.sn")); softwareJson.addProperty("jiaoguanyi_version", ApkUtils.getAPPVersionName(mContext, "com.jiaoguanyi.os")); softwareJson.addProperty("gankao_version", ApkUtils.getAPPVersionName(mContext, "com.gankao.gkwxhd")); @@ -1921,7 +1898,7 @@ public class NetInterfaceManager { nowJson.addProperty("hardware", hardware); nowJson.addProperty("software", software); String string = GsonUtils.toJSONString(nowJson); - String oldString = mMMKV.decodeString(UrlAddress.UPDATE_SNINFO, ""); + String oldString = mMMKV.decodeString(UrlAddress.UPDATE_SN_INFO, ""); Log.e(TAG, "updateAdminInfo: oldString = " + oldString); Log.e(TAG, "updateAdminInfo: string = " + string); if (oldString.equals(string)) { @@ -1945,7 +1922,7 @@ public class NetInterfaceManager { @Override public void onNext(@NonNull BaseResponse baseResponse) { if (baseResponse.code == 200) { - mMMKV.encode(UrlAddress.UPDATE_SNINFO, string); + mMMKV.encode(UrlAddress.UPDATE_SN_INFO, string); } Log.e("updateAdminInfo", "onNext: " + baseResponse); @@ -2127,18 +2104,18 @@ public class NetInterfaceManager { } public void getSystemSettings(BehaviorSubject lifecycle, CompleteCallback callback) { - getsettingControl() + getSettingControl() .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) .subscribe(getSystemSettingsObserver(callback)); } public void getSystemSettings(CompleteCallback callback) { - getsettingControl() + getSettingControl() .subscribe(getSystemSettingsObserver(callback)); } public void getSystemSettings() { - getsettingControl() + getSettingControl() .subscribe(getSystemSettingsObserver(null)); } @@ -2308,7 +2285,7 @@ public class NetInterfaceManager { JsonObject jsonObject = GsonUtils.getJsonObject(jsonString); String ids = jsonObject.get("ids").getAsString(); String packages = jsonObject.get("package").getAsString(); - JGYUtils.getInstance().writeDeselectIDtoSystem(ids, packages); + JgyUtils.getInstance().writeDeselectIDtoSystem(ids, packages); } else { Log.e("getAppInside", "onNext: " + baseResponse.msg); Settings.System.putString(crv, CommonConfig.AOLE_ACTION_APP_FORBID_ID, " "); @@ -2710,7 +2687,7 @@ public class NetInterfaceManager { Log.e(TAG, "installOverallApp: " + packageList); for (OverallAppBean overallAppBean : overallAppBeanList) { String packages = overallAppBean.getApp_package(); - if (!JGYUtils.mGlobalUpdatePkgs.contains(packages)) { + if (!JgyUtils.mGlobalUpdatePkgs.contains(packages)) { continue; } String url = overallAppBean.getApp_url(); @@ -3206,7 +3183,7 @@ public class NetInterfaceManager { @Override public void onComplete() { Log.e("getAppAndWhite", "onComplete: "); - JGYUtils.getInstance().putBuiltInApps(); + JgyUtils.getInstance().putBuiltInApps(); if (callback != null) { callback.onComplete(); } diff --git a/app/src/main/java/com/fuying/sn/network/UrlAddress.java b/app/src/main/java/com/fuying/sn/network/UrlAddress.java index 6be52d3..fa89924 100644 --- a/app/src/main/java/com/fuying/sn/network/UrlAddress.java +++ b/app/src/main/java/com/fuying/sn/network/UrlAddress.java @@ -4,80 +4,30 @@ public class UrlAddress { /*主页接口*/ static final String ROOT_URL = "http://47.111.23.154/android/"; - //不需要做缓存的接口 - - /*获取app桌面管控配置*/ - public final static String GET_APP_TIME_CONTROL = "Control/getAppTimeControl"; - /*获取整机管控配置*/ - public final static String GET_SN_TIME_CONTROL = "Control/getSnTimeControl"; - /*获取所有应用时间*/ - public final static String GET_MY_APP_LIST = "app/myAppList"; - - //不需要在后台添加sn的接口 - /*获取所有全局更新*/ - public final static String GE_TOVERALL_APPBYPLATFORM = "app/overallAppByPlatform"; - /*获取应用内置白名单*/ - public static final String GET_APP_AND_WHITE = "getAppAndWhite"; - /*获取管理员上传的应用*/ - public final static String GET_ADMIN_APP = "getAdminApp"; - /*根据包名获取更新*/ - public final static String GET_NEWESTAPPUPDATE = "app/newestAppUpdate"; - /*发送设备基本信息*/ - public final static String UPDATE_SNINFO = "sn/updateAdminSn"; - /*绑定设备消息*/ public final static String BIND_DEVICES = "sn/bindSn"; - + /*获取设备绑定状态*/ public final static String GET_SN_BIND = "sn/getSnBind"; - + /*设备信息接口*/ + public static final String SN_INFO = "sn/getSnInfo"; + /*获取用户头像和信息*/ + public static final String GET_USER_AVATAR_INFO = "sn/getUserAvatarInfo"; /*获取批次*/ public static final String GET_BATCH = "sn/getBatch"; /*获取标签*/ public static final String GET_TAG = "sn/get-tag"; - /*设备信息接口*/ - public static final String SNINFO = "sn/getSnInfo"; - - /*获取正在运行的app*/ - public static final String RUN_NEW_APP = "app/runNewApp"; - /*获取所有应用*/ - public final static String GET_ALL_PACKAGE = "app/queryAllApp"; - /*获取系统设置*/ - public final static String GET_SETTINGS = "control/getSetting"; - /*浏览器网址管控*/ - public final static String SET_BROWSER_URL = "control/getBrowser"; - /*浏览器书签管控*/ - public final static String SET_BROWSER_LABEL = "control/getLabel"; - /*获取强制下载*/ - public final static String GET_FORCE_INSTALL = "app/getForceDownload"; + /*发送设备基本信息*/ + public final static String UPDATE_SN_INFO = "sn/updateAdminSn"; /*获取app管控*/ public final static String GET_APP_START = "sn/querySnAppStart"; - /*发app跳转管控*/ + /*app跳转管控*/ public final static String GET_APP_JUMP = "sn/querySnJump"; - /*全局黑名单列表*/ - public final static String GLOBAL_BLACKLIST = "common/blacklist"; - /*app内部管控*/ - public final static String QUERY_APP_INSIDE = "control/queryAppInside"; - /*发送卸载或者安装信息*/ - public final static String SEND_INSTALLEDORREMOVED = "app/addAppInstall"; - + /*获取时间管控*/ + public final static String GET_TIME_CONTROL = "sn/getTimeControl"; /*上传屏幕截图*/ public final static String UPLOAD_SCREEN_SNAPSHOT = "sn/uploadScreenshot"; - - /*获取时间管控*/ - public final static String GET_TIME_CONTROL = "sn/getTimeControlControl"; - /*获取用户头像和信息*/ - public static final String GET_USER_AVATAR_INFO = "sn/getUserAvatarInfo"; - /*获取小程序二维码*/ - public static final String GET_APPLET_QRCODE = "file/getAppletQrCode"; - /*获取操作指南*/ - public static final String GET_OPERATION_GUIDE = "file/getFiles"; /*上传控制面版截图*/ public static final String UPLOAD_CONTROL_SCREENSHOT = "sn/uploadControlScreenshot"; - /*获取是否为网课模式*/ - public static final String GET_CLOUD_LESSON_SETTING = "Control/getCloudLessonSetting"; - /*应用使用记录*/ - public static final String APP_USAGE_RECORD = "appUsageRecord"; - /*获取屏幕管控*/ public final static String GET_SCREEN_LOCK = "sn/getScreenshot"; /*获取锁屏密码*/ @@ -97,6 +47,52 @@ public class UrlAddress { public static final String UPLOAD_IS_LOG_FILE = "sn/uploadIsLogFile"; + /*获取所有应用时间*/ + public final static String GET_MY_APP_LIST = "app/myAppList"; + /*获取所有全局更新*/ + public final static String GE_TOVERALL_APPBYPLATFORM = "app/overallAppByPlatform"; + /*根据包名获取更新*/ + public final static String GET_NEWEST_APPUPDATE = "app/newestAppUpdate"; + /*获取正在运行的app*/ + public static final String RUN_NEW_APP = "app/runNewApp"; + /*获取所有应用*/ + public final static String GET_ALL_PACKAGE = "app/queryAllApp"; + /*获取强制下载*/ + public final static String GET_FORCE_INSTALL = "app/getForceDownload"; + /*发送卸载或者安装信息*/ + public final static String SEND_INSTALLEDORREMOVED = "app/addAppInstall"; + + /*获取系统设置*/ + public final static String GET_SETTINGS = "control/getSetting"; + /*浏览器网址管控*/ + public final static String SET_BROWSER_URL = "control/getBrowser"; + /*浏览器书签管控*/ + public final static String SET_BROWSER_LABEL = "control/getLabel"; + /*app内部管控*/ + public final static String QUERY_APP_INSIDE = "control/queryAppInside"; + /*获取是否为网课模式*/ + public static final String GET_CLOUD_LESSON_SETTING = "Control/getCloudLessonSetting"; + /*获取app桌面管控配置*/ + public final static String GET_APP_TIME_CONTROL = "Control/getAppTimeControl"; + /*获取整机管控配置*/ + public final static String GET_SN_TIME_CONTROL = "Control/getSnTimeControl"; + + + /*获取小程序二维码*/ + public static final String GET_APPLET_QRCODE = "file/getAppletQrCode"; + /*获取操作指南*/ + public static final String GET_OPERATION_GUIDE = "file/getFiles"; + + /*全局黑名单列表*/ + public final static String GLOBAL_BLACKLIST = "common/blacklist"; + + /*获取应用内置白名单*/ + public static final String GET_APP_AND_WHITE = "getAppAndWhite"; + /*获取管理员上传的应用*/ + public final static String GET_ADMIN_APP = "getAdminApp"; + /*应用使用记录*/ + public static final String APP_USAGE_RECORD = "appUsageRecord"; + /*获取公网IP*/ public static final String SHOUHU_CITYJSON = "http://pv.sohu.com/cityjson/"; } diff --git a/app/src/main/java/com/fuying/sn/network/api/NewestAppUpdate.java b/app/src/main/java/com/fuying/sn/network/api/NewestAppUpdate.java index 769427b..e38a44d 100644 --- a/app/src/main/java/com/fuying/sn/network/api/NewestAppUpdate.java +++ b/app/src/main/java/com/fuying/sn/network/api/NewestAppUpdate.java @@ -9,7 +9,7 @@ import retrofit2.http.GET; import retrofit2.http.Query; public interface NewestAppUpdate { - @GET(UrlAddress.GET_NEWESTAPPUPDATE) + @GET(UrlAddress.GET_NEWEST_APPUPDATE) Observable> getAppUpdate( @Query("packageName") String packageName, @Query("versionCode") String versionCode, diff --git a/app/src/main/java/com/fuying/sn/network/api/SNInfoApi.java b/app/src/main/java/com/fuying/sn/network/api/SnApi.java similarity index 85% rename from app/src/main/java/com/fuying/sn/network/api/SNInfoApi.java rename to app/src/main/java/com/fuying/sn/network/api/SnApi.java index d6cfc48..7b84624 100644 --- a/app/src/main/java/com/fuying/sn/network/api/SNInfoApi.java +++ b/app/src/main/java/com/fuying/sn/network/api/SnApi.java @@ -8,8 +8,8 @@ import io.reactivex.rxjava3.core.Observable; import retrofit2.http.GET; import retrofit2.http.Query; -public interface SNInfoApi { - @GET(UrlAddress.SNINFO) +public interface SnApi { + @GET(UrlAddress.SN_INFO) Observable> getsninfo( @Query("sn") String sn ); diff --git a/app/src/main/java/com/fuying/sn/network/api/UpdateAdminSn.java b/app/src/main/java/com/fuying/sn/network/api/UpdateAdminSn.java index dfe98ff..0457a26 100644 --- a/app/src/main/java/com/fuying/sn/network/api/UpdateAdminSn.java +++ b/app/src/main/java/com/fuying/sn/network/api/UpdateAdminSn.java @@ -10,7 +10,7 @@ import retrofit2.http.POST; public interface UpdateAdminSn { @FormUrlEncoded - @POST(UrlAddress.UPDATE_SNINFO) + @POST(UrlAddress.UPDATE_SN_INFO) Observable sendAdminSn( @Field("sn") String sn, @Field("address") String address, diff --git a/app/src/main/java/com/fuying/sn/network/interceptor/PostCacheInterceptor.java b/app/src/main/java/com/fuying/sn/network/interceptor/PostCacheInterceptor.java index 47b37ab..3e2e998 100644 --- a/app/src/main/java/com/fuying/sn/network/interceptor/PostCacheInterceptor.java +++ b/app/src/main/java/com/fuying/sn/network/interceptor/PostCacheInterceptor.java @@ -4,10 +4,11 @@ import android.text.TextUtils; import com.blankj.utilcode.util.LogUtils; import com.fuying.sn.disklrucache.DiskLruCacheHelper; -import com.fuying.sn.utils.JGYUtils; +import com.fuying.sn.utils.JgyUtils; import java.io.IOException; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import okhttp3.Interceptor; import okhttp3.MediaType; @@ -62,7 +63,7 @@ public class PostCacheInterceptor implements Interceptor { } //没有网络连接的时候读取缓存 - if (!JGYUtils.getInstance().isNetworkConnected()) { + if (!JgyUtils.getInstance().isNetworkConnected()) { LogUtils.d("no network connected jujge cache available"); if (cacheResponse != null) { LogUtils.d("no network connected, return cache: " + cacheResponse); @@ -148,7 +149,7 @@ public class PostCacheInterceptor implements Interceptor { private String createKey(Request request) { RequestBody requestBody = request.body(); - Charset charset = Charset.forName("UTF-8"); + Charset charset = StandardCharsets.UTF_8; String url = request.url().toString(); StringBuilder sb = new StringBuilder(); sb.append(url + "&"); @@ -237,7 +238,7 @@ public class PostCacheInterceptor implements Interceptor { buffer = source.buffer(); Charset charset = response.body().contentType().charset(); if (charset == null) { - charset = Charset.forName("UTF-8"); + charset = StandardCharsets.UTF_8; } caches[REPONSE_BODY] = buffer.clone().readString(charset); } catch (IOException e) { diff --git a/app/src/main/java/com/fuying/sn/push/PushManager.java b/app/src/main/java/com/fuying/sn/push/PushManager.java index dff7c9f..62d55ac 100644 --- a/app/src/main/java/com/fuying/sn/push/PushManager.java +++ b/app/src/main/java/com/fuying/sn/push/PushManager.java @@ -37,7 +37,7 @@ import com.fuying.sn.utils.ApkUtils; import com.fuying.sn.utils.CacheUtils; import com.fuying.sn.utils.CmdUtil; import com.fuying.sn.utils.FileUtils; -import com.fuying.sn.utils.JGYUtils; +import com.fuying.sn.utils.JgyUtils; import com.fuying.sn.utils.SPUtils; import com.fuying.sn.utils.ServiceAliveUtils; import com.fuying.sn.utils.ToastUtil; @@ -319,7 +319,7 @@ public class PushManager { case JIGUANG_CAMRERA: ToastUtil.debugShow("收到推送消息: 摄像头管控"); setCameta(extras); - JGYUtils.getInstance().updateForbidList(); + JgyUtils.getInstance().updateForbidList(); break; case JIGUANG_PHONE: ToastUtil.debugShow("收到推送消息: 电话管控"); @@ -388,8 +388,8 @@ public class PushManager { ToastUtil.debugShow("收到推送消息: 强制停止应用"); JsonObject killJSONObject = GsonUtils.getJsonObject(extras); String packages = killJSONObject.get("app_package").getAsString(); - JGYUtils.getInstance().killPackage(packages); - JGYUtils.getInstance().gotoLauncher(); + JgyUtils.getInstance().killPackage(packages); + JgyUtils.getInstance().gotoLauncher(); Log.e(TAG, extras); break; case JIGUANG_LOCK_SCREEN: @@ -692,7 +692,7 @@ public class PushManager { NetInterfaceManager.getInstance().SendAppInstallInfo(); NetInterfaceManager.getInstance().getAppAndWhite(); NetInterfaceManager.getInstance().getSnInfo(); - if (JGYUtils.getInstance().isScreenOn()) { + if (JgyUtils.getInstance().isScreenOn()) { NetInterfaceManager.getInstance().screenshot(); } } @@ -805,7 +805,7 @@ public class PushManager { } JsonObject extra = GsonUtils.getJsonObject(jsonString); String packages = extra.get("package").getAsString(); - JGYUtils.getInstance().addPkgToForbid(packages); + JgyUtils.getInstance().addPkgToForbid(packages); ToastUtil.debugShow("收到应用安装消息:包名" + packages); String url = extra.get("url").getAsString(); if (TextUtils.isEmpty(url)) { @@ -1280,7 +1280,7 @@ public class PushManager { JsonObject jsonObject = GsonUtils.getJsonObject(jsonString); int search_topic = jsonObject.get("search_topic").getAsInt(); Log.e(TAG, "searchTopic: put = " + SPUtils.put(mContext, "search_topic", search_topic)); - JGYUtils.getInstance().updateForbidList(); + JgyUtils.getInstance().updateForbidList(); } private void setAlarmCLock(String ex) { @@ -1354,7 +1354,7 @@ public class PushManager { JsonElement jsonElement = jsonObject.get("desktop_app"); if (jsonElement != null) { String packeges = jsonElement.getAsString(); - JGYUtils.getInstance().setDefaultDesktop(packeges); + JgyUtils.getInstance().setDefaultDesktop(packeges); } else { } @@ -1365,7 +1365,7 @@ public class PushManager { JsonElement jsonElement = jsonObject.get("browser_app"); if (jsonElement != null) { String packeges = jsonElement.getAsString(); - JGYUtils.getInstance().setDefaultBrowser(packeges); + JgyUtils.getInstance().setDefaultBrowser(packeges); } else { Log.e(TAG, "setDefaultBrowser: packeges is NULL"); } @@ -1374,16 +1374,16 @@ public class PushManager { private void setDefaultInputMethod(String extras) { JsonObject jsonObject = GsonUtils.getJsonObject(extras); String packeges = jsonObject.get("typewriting_app").getAsString(); - JGYUtils.getInstance().setDefaultInputMethod(packeges); + JgyUtils.getInstance().setDefaultInputMethod(packeges); } private void oneKeyNetwork(String extras) { JsonObject jsonObject = GsonUtils.getJsonObject(extras); int is_network = jsonObject.get("is_network").getAsInt(); if (is_network == 1) { - JGYUtils.getInstance().oneKeyDisconnection(); + JgyUtils.getInstance().oneKeyDisconnection(); } else { - JGYUtils.getInstance().restorrNetwork(); + JgyUtils.getInstance().restorrNetwork(); } } diff --git a/app/src/main/java/com/fuying/sn/push/tpush/Constants.java b/app/src/main/java/com/fuying/sn/push/tpush/Constants.java deleted file mode 100644 index ea76bd0..0000000 --- a/app/src/main/java/com/fuying/sn/push/tpush/Constants.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.fuying.sn.push.tpush; - -/** - * Created by chacewang on 2019/7/5. - */ - -public class Constants { - public static final int TEST_LOCAL_NOTIFICATION = 1; - public static final int TEST_NOTIFICATION = 2; - public static final int TEST_SET_TAG = 3; - public static final int TEST_DEL_TAG = 4; - public static final int TEST_SET_ACCOUNT = 5; - public static final int TEST_DEL_ACCOUNT = 6; - - public static final String LOCAL_NOTIFICATION_TITLE = "localtest"; - public static final String TEST_TAG_NAME = "DiagnosisTag"; -} diff --git a/app/src/main/java/com/fuying/sn/push/tpush/MessageReceiver.java b/app/src/main/java/com/fuying/sn/push/tpush/MessageReceiver.java deleted file mode 100644 index d3aa2ed..0000000 --- a/app/src/main/java/com/fuying/sn/push/tpush/MessageReceiver.java +++ /dev/null @@ -1,297 +0,0 @@ -package com.fuying.sn.push.tpush; - -import android.content.Context; -import android.content.Intent; -import android.text.TextUtils; -import android.util.Log; -import android.widget.Toast; - -import com.fuying.sn.push.tpush.common.NotificationService; -import com.fuying.sn.push.tpush.po.XGNotification; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.tencent.android.tpush.NotificationAction; -import com.tencent.android.tpush.XGPushBaseReceiver; -import com.tencent.android.tpush.XGPushClickedResult; -import com.tencent.android.tpush.XGPushRegisterResult; -import com.tencent.android.tpush.XGPushShowedResult; -import com.tencent.android.tpush.XGPushTextMessage; - -import java.text.SimpleDateFormat; -import java.util.Calendar; - -public class MessageReceiver extends XGPushBaseReceiver { - public static final String UPDATE_LISTVIEW_ACTION = "com.qq.xgdemo.activity.UPDATE_LISTVIEW"; - public static final String TEST_ACTION = "com.qq.xgdemo.activity.TEST_ACTION"; - public static final String LogTag = "xg.test"; - - private static final String TAG = "MessageReceiver"; - - /** - * 消息透传处理 - * - * @param context - * @param message 解析自定义的 JSON - */ - @Override - public void onTextMessage(Context context, XGPushTextMessage message) { - - String text = "收到消息:" + message.toString(); - // 获取自定义key-value - String customContent = message.getCustomContent(); - if (customContent != null && customContent.length() != 0) { - JsonObject obj = JsonParser.parseString(customContent).getAsJsonObject(); - // key1为前台配置的key - if (!TextUtils.isEmpty(obj.get("key").getAsString())) { - String value = obj.get("key").getAsString(); - Log.d(LogTag, "get custom value:" + value); - } - // ... - } - // APP自主处理消息的过程... - Log.e(LogTag, text); - show(context, text); - processCustomMessage(context, message); - } - - /** - * 通知展示 - * - * @param context - * @param notifiShowedRlt 包含通知的内容 - */ - @Override - public void onNotificationShowedResult(Context context, XGPushShowedResult notifiShowedRlt) { - if (context == null || notifiShowedRlt == null) { - return; - } - XGNotification notific = new XGNotification(); - notific.setMsg_id(notifiShowedRlt.getMsgId()); - notific.setTitle(notifiShowedRlt.getTitle()); - notific.setContent(notifiShowedRlt.getContent()); - // notificationActionType==1为Activity,2为url,3为intent - notific.setNotificationActionType(notifiShowedRlt - .getNotificationActionType()); - // Activity,url,intent都可以通过getActivity()获得 - notific.setActivity(notifiShowedRlt.getActivity()); - notific.setUpdate_time(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") - .format(Calendar.getInstance().getTime())); - NotificationService.getInstance(context).save(notific); - - Intent testIntent = new Intent(TEST_ACTION); - if (notifiShowedRlt.getTitle().equals(Constants.LOCAL_NOTIFICATION_TITLE)) { - testIntent.putExtra("step", Constants.TEST_LOCAL_NOTIFICATION); - } else { - testIntent.putExtra("step", Constants.TEST_NOTIFICATION); - } - context.sendBroadcast(testIntent); - - Intent viewIntent = new Intent(UPDATE_LISTVIEW_ACTION); - context.sendBroadcast(viewIntent); - show(context, "您有1条新消息, " + "通知被展示 , " + notifiShowedRlt.toString()); - Log.d(LogTag, "您有1条新消息, " + "通知被展示 , " + notifiShowedRlt.toString() + ", PushChannel:" + notifiShowedRlt.getPushChannel()); - } - - /** - * 注册回调 - * - * @param context - * @param errorCode 0 为成功,其它为错误码 - */ - @Override - public void onRegisterResult(Context context, int errorCode, XGPushRegisterResult message) { - if (context == null || message == null) { - return; - } - String text = ""; - if (errorCode == XGPushBaseReceiver.SUCCESS) { - // 在这里拿token - String token = message.getToken(); - text = "注册成功1. token:" + token; - } else { - text = message + "注册失败,错误码:" + errorCode; - } - Log.d(LogTag, text); - show(context, text); - } - - /** - * 反注册回调 - * - * @param context - * @param errorCode 0 为成功,其它为错误码 - */ - @Override - public void onUnregisterResult(Context context, int errorCode) { - if (context == null) { - return; - } - String text = ""; - if (errorCode == XGPushBaseReceiver.SUCCESS) { - text = "反注册成功"; - } else { - text = "反注册失败" + errorCode; - } - Log.d(LogTag, text); - show(context, text); - - } - - /** - * 设置标签回调 - * - * @param context - * @param errorCode 0 为成功,其它为错误码 - * @param tagName 设置的 TAG - */ - @Override - public void onSetTagResult(Context context, int errorCode, String tagName) { - if (context == null) { - return; - } - String text = ""; - if (errorCode == XGPushBaseReceiver.SUCCESS) { - text = "\"" + tagName + "\"设置成功"; - } else { - text = "\"" + tagName + "\"设置失败,错误码:" + errorCode; - } - Log.d(LogTag, text); - show(context, text); - - Intent testIntent = new Intent(TEST_ACTION); - testIntent.putExtra("step", Constants.TEST_SET_TAG); - context.sendBroadcast(testIntent); - } - - /** - * 删除标签的回调 - * - * @param context - * @param errorCode 0 为成功,其它为错误码 - * @param tagName 设置的 TAG - */ - @Override - public void onDeleteTagResult(Context context, int errorCode, String tagName) { - if (context == null) { - return; - } - String text = ""; - if (errorCode == XGPushBaseReceiver.SUCCESS) { - text = "\"" + tagName + "\"删除成功"; - } else { - text = "\"" + tagName + "\"删除失败,错误码:" + errorCode; - } - Log.d(LogTag, text); - show(context, text); - - Intent testIntent = new Intent(TEST_ACTION); - testIntent.putExtra("step", Constants.TEST_DEL_TAG); - context.sendBroadcast(testIntent); - } - - /** - * 设置账号回调 - * - * @param context - * @param errorCode 0 为成功,其它为错误码 - * @param account 设置的账号 - */ - @Override - public void onSetAccountResult(Context context, int errorCode, String account) { - Intent testIntent = new Intent(TEST_ACTION); - testIntent.putExtra("step", Constants.TEST_SET_ACCOUNT); - context.sendBroadcast(testIntent); - } - - - /** - * 删除账号回调 - * - * @param context - * @param errorCode 0 为成功,其它为错误码 - * @param account 设置的账号 - */ - @Override - public void onDeleteAccountResult(Context context, int errorCode, String account) { - Intent testIntent = new Intent(TEST_ACTION); - testIntent.putExtra("step", Constants.TEST_DEL_ACCOUNT); - context.sendBroadcast(testIntent); - } - - @Override - public void onSetAttributeResult(Context context, int i, String s) { - - } - - @Override - public void onDeleteAttributeResult(Context context, int i, String s) { - - } - - @Override - public void onQueryTagsResult(Context context, int errorCode, String data, String operateName) { - Log.i(LogTag, "action - onQueryTagsResult, errorCode:" + errorCode + ", operateName:" + operateName + ", data: " + data); - } - - /** - * 通知点击回调 actionType=1为该消息被清除,actionType=0为该消息被点击 - * - * @param context - * @param message 包含被点击通知的内容 - */ - @Override - public void onNotificationClickedResult(Context context, XGPushClickedResult message) { - if (context == null || message == null) { - return; - } - String text = ""; - if (message.getActionType() == NotificationAction.clicked.getType()) { - // 通知在通知栏被点击啦。。。。。 - // APP自己处理点击的相关动作 - // 这个动作可以在activity的onResume也能监听,请看第3点相关内容 - text = "通知被打开 :" + message; - } else if (message.getActionType() == NotificationAction.delete.getType()) { - // 通知被清除啦。。。。 - // APP自己处理通知被清除后的相关动作 - text = "通知被清除 :" + message; - } - Toast.makeText(context, "广播接收到通知被点击:" + message.toString(), - Toast.LENGTH_SHORT).show(); - // 获取自定义key-value - String customContent = message.getCustomContent(); - if (customContent != null && customContent.length() != 0) { - JsonObject obj = JsonParser.parseString(customContent).getAsJsonObject(); - // key1为前台配置的key - if (!TextUtils.isEmpty(obj.get("key").getAsString())) { - String value = obj.get("key").getAsString(); - Log.d(LogTag, "get custom value:" + value); - } - // ... - } - // APP自主处理的过程。。。 - Log.d(LogTag, text); - show(context, text); - } - - private void show(Context context, String text) { -// Toast.makeText(context, text, Toast.LENGTH_SHORT).show(); - } - - private void processCustomMessage(Context context, XGPushTextMessage message) { - if (context == null || message == null) { - return; - } - - String title = message.getTitle(); - String content = message.getContent(); - JsonObject extrasJson = JsonParser.parseString(content).getAsJsonObject(); - - String extras = ""; - if (extrasJson.get("extras") != null) { - extras = extrasJson.get("extras").toString(); - } - -// PushManager.getInstance().setPushContent(title, extras); - } - -} diff --git a/app/src/main/java/com/fuying/sn/push/tpush/common/DBOpenHelper.java b/app/src/main/java/com/fuying/sn/push/tpush/common/DBOpenHelper.java deleted file mode 100644 index 1504e27..0000000 --- a/app/src/main/java/com/fuying/sn/push/tpush/common/DBOpenHelper.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.fuying.sn.push.tpush.common; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; - -public class DBOpenHelper extends SQLiteOpenHelper { - - public DBOpenHelper(Context context) { - super(context, "XGExample.db", null, 1); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE notification (id integer primary key autoincrement,msg_id varchar(64),title varchar(128),activity varchar(256),notificationActionType varchar(512),content text,update_time varchar(16))"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - - } - -} diff --git a/app/src/main/java/com/fuying/sn/push/tpush/common/NotificationService.java b/app/src/main/java/com/fuying/sn/push/tpush/common/NotificationService.java deleted file mode 100644 index 4cda4dc..0000000 --- a/app/src/main/java/com/fuying/sn/push/tpush/common/NotificationService.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.fuying.sn.push.tpush.common; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; - -import com.fuying.sn.push.tpush.po.XGNotification; - -import java.util.ArrayList; -import java.util.List; - -public class NotificationService { - private DBOpenHelper dbOpenHelper; - private static NotificationService instance = null; - - public NotificationService(Context context) { - this.dbOpenHelper = new DBOpenHelper(context); - } - - public synchronized static NotificationService getInstance(Context ctx) { - if (null == instance) { - instance = new NotificationService(ctx); - } - return instance; - } - - public void save(XGNotification notification) { - SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); - ContentValues values = new ContentValues(); - values.put("msg_id", notification.getMsg_id()); - values.put("title", notification.getTitle()); - values.put("content", notification.getContent()); - values.put("activity", notification.getActivity()); - values.put("notificationActionType", notification.getNotificationActionType()); - values.put("update_time", notification.getUpdate_time()); - db.insert("notification", null, values); - } - - public void delete(Integer id) { - SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); - db.delete("notification", "id=?", new String[] { id.toString() }); - } - - public void deleteAll() { - SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); - db.delete("notification", "", null); - } - - public void update(XGNotification notification) { - SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); - ContentValues values = new ContentValues(); - values.put("msg_id", notification.getMsg_id()); - values.put("title", notification.getTitle()); - values.put("content", notification.getContent()); - values.put("activity", notification.getActivity()); - values.put("notificationActionType", notification.getNotificationActionType()); - values.put("update_time", notification.getUpdate_time()); - db.update("notification", values, "id=?", new String[] { notification - .getId().toString() }); - } - - public XGNotification find(Integer id) { - SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); - Cursor cursor = db - .query("notification", - new String[] { "id,msg_id,title,content,activity,notificationActionType,update_time" }, - "id=?", new String[] { id.toString() }, null, null, - null, "1"); - try { - if (cursor.moveToFirst()) { - return new XGNotification(cursor.getInt(cursor - .getColumnIndex("id")), cursor.getLong(cursor - .getColumnIndex("msg_id")), cursor.getString(cursor - .getColumnIndex("title")), cursor.getString(cursor - .getColumnIndex("content")), cursor.getString(cursor - .getColumnIndex("activity")), cursor.getInt(cursor - .getColumnIndex("notificationActionType")), cursor.getString(cursor - .getColumnIndex("update_time"))); - } - return null; - } finally { - cursor.close(); - } - } - - public List getScrollData(int currentPage, int lineSize, - String msg_id) { - String firstResult = String.valueOf((currentPage - 1) * lineSize); - SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); - Cursor cursor = null; - try { - if (msg_id == null || "".equals(msg_id)) { - cursor = db - .query("notification", - new String[] { "id,msg_id,title,content,activity,notificationActionType,update_time" }, - null, null, null, null, "update_time DESC", - firstResult + "," + lineSize); - } else { - cursor = db - .query("notification", - new String[] { "id,msg_id,title,content,activity,notificationActionType,update_time" }, - "msg_id like ?", new String[] { msg_id + "%" }, - null, null, "update_time DESC", firstResult - + "," + lineSize); - } - List notifications = new ArrayList(); - while (cursor.moveToNext()) { - notifications.add(new XGNotification(cursor.getInt(cursor - .getColumnIndex("id")), cursor.getLong(cursor - .getColumnIndex("msg_id")), cursor.getString(cursor - .getColumnIndex("title")), cursor.getString(cursor - .getColumnIndex("content")), cursor.getString(cursor - .getColumnIndex("activity")), cursor.getInt(cursor - .getColumnIndex("notificationActionType")), cursor.getString(cursor - .getColumnIndex("update_time")))); - } - return notifications; - } finally { - cursor.close(); - } - } - - public int getCount() { - SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); - Cursor cursor = db.rawQuery("select count(*) from notification", null); - try { - cursor.moveToFirst(); - return cursor.getInt(0); - } finally { - cursor.close(); - } - } -} diff --git a/app/src/main/java/com/fuying/sn/push/tpush/po/XGNotification.java b/app/src/main/java/com/fuying/sn/push/tpush/po/XGNotification.java deleted file mode 100644 index 438d06b..0000000 --- a/app/src/main/java/com/fuying/sn/push/tpush/po/XGNotification.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.fuying.sn.push.tpush.po; - -public class XGNotification { - private Integer id; - private Long msg_id; - private String title; - private String content; - private String activity; - private int notificationActionType; - private String update_time; - - public XGNotification() { - - } - - public XGNotification(Integer id, Long msg_id, String title, - String content, String activity, int notificationActionType, String update_time) { - super(); - this.id = id; - this.msg_id = msg_id; - this.title = title; - this.content = content; - this.activity = activity; - this.notificationActionType = notificationActionType; - this.update_time = update_time; - } - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public Long getMsg_id() { - return msg_id; - } - - public void setMsg_id(Long msg_id) { - this.msg_id = msg_id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public String getUpdate_time() { - return update_time; - } - - public void setUpdate_time(String update_time) { - this.update_time = update_time; - } - - public String getActivity() { - return activity; - } - - public void setActivity(String activity) { - this.activity = activity; - } - - public int getNotificationActionType() { - return notificationActionType; - } - - public void setNotificationActionType(int notificationActionType) { - this.notificationActionType = notificationActionType; - } -} diff --git a/app/src/main/java/com/fuying/sn/receiver/APKinstallReceiver.java b/app/src/main/java/com/fuying/sn/receiver/APKinstallReceiver.java index 35776b8..af1e6b0 100644 --- a/app/src/main/java/com/fuying/sn/receiver/APKinstallReceiver.java +++ b/app/src/main/java/com/fuying/sn/receiver/APKinstallReceiver.java @@ -11,7 +11,7 @@ import com.fuying.sn.config.CommonConfig; import com.fuying.sn.manager.ControlManager; import com.fuying.sn.network.NetInterfaceManager; import com.fuying.sn.utils.CacheUtils; -import com.fuying.sn.utils.JGYUtils; +import com.fuying.sn.utils.JgyUtils; import com.fuying.sn.utils.SPUtils; import java.util.concurrent.TimeUnit; @@ -38,7 +38,7 @@ public class APKinstallReceiver extends BroadcastReceiver { // an Intent broadcast. String action = intent.getAction(); // ApkUtils.addShortcut(context); - JGYUtils.getInstance().cleanLauncherCache(); + JgyUtils.getInstance().cleanLauncherCache(); ControlManager.getInstance().setDefaultApp(); Log.e(TAG, "onReceive: " + "action = " + action); String state; @@ -50,8 +50,8 @@ public class APKinstallReceiver extends BroadcastReceiver { switch (action) { case Intent.ACTION_PACKAGE_ADDED: state = "安装了:"; - JGYUtils.RemoveTask(context, packageName); - JGYUtils.getInstance().putBuiltInApps(); + JgyUtils.RemoveTask(context, packageName); + JgyUtils.getInstance().putBuiltInApps(); break; case Intent.ACTION_PACKAGE_REPLACED: cleanLauncher3Cache(); @@ -66,10 +66,10 @@ public class APKinstallReceiver extends BroadcastReceiver { } Log.e(TAG, "sendAppInfo: " + state + packageName); newAppListener.setNewAppListener(packageName); - if (JGYUtils.PACKAGE_APPSTORE.equals(packageName)) { + if (JgyUtils.PACKAGE_APPSTORE.equals(packageName)) { //启动应用市场 // JGYUtils.getInstance().wakeUpDeviceInfo(); - } else if (JGYUtils.PACKAGE_UPDATETOOLS.equals(packageName)) { + } else if (JgyUtils.PACKAGE_UPDATETOOLS.equals(packageName)) { //启动升级组件 // JGYUtils.getInstance().wakeUpUpdateTools(); } diff --git a/app/src/main/java/com/fuying/sn/receiver/BootReceiver.java b/app/src/main/java/com/fuying/sn/receiver/BootReceiver.java index 41e34ed..0363aa6 100644 --- a/app/src/main/java/com/fuying/sn/receiver/BootReceiver.java +++ b/app/src/main/java/com/fuying/sn/receiver/BootReceiver.java @@ -5,18 +5,13 @@ import android.content.Context; import android.content.Intent; import android.util.Log; -import com.baidu.location.BDAbstractLocationListener; -import com.baidu.location.BDLocation; -import com.baidu.location.LocationClient; import com.fuying.sn.config.CommonConfig; -import com.fuying.sn.manager.AmapManager; -import com.fuying.sn.network.NetInterfaceManager; import com.fuying.sn.service.ControlPanelService; -import com.fuying.sn.service.GuardService; -import com.fuying.sn.service.main.MainService; -import com.fuying.sn.service.ManagerService; import com.fuying.sn.service.DownloadService; +import com.fuying.sn.service.GuardService; +import com.fuying.sn.service.ManagerService; import com.fuying.sn.service.StepService; +import com.fuying.sn.service.main.MainService; import com.tencent.mmkv.MMKV; diff --git a/app/src/main/java/com/fuying/sn/service/DownloadService.java b/app/src/main/java/com/fuying/sn/service/DownloadService.java index 8e2a92b..ac6ed01 100644 --- a/app/src/main/java/com/fuying/sn/service/DownloadService.java +++ b/app/src/main/java/com/fuying/sn/service/DownloadService.java @@ -17,12 +17,12 @@ import com.arialyy.annotations.Download; import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.task.DownloadTask; import com.blankj.utilcode.util.ToastUtils; -import com.google.gson.JsonObject; import com.fuying.sn.KeepAliveConnection; import com.fuying.sn.R; +import com.fuying.sn.gson.GsonUtils; import com.fuying.sn.service.main.MainService; import com.fuying.sn.utils.ApkUtils; -import com.fuying.sn.gson.GsonUtils; +import com.google.gson.JsonObject; import java.io.File; @@ -30,6 +30,15 @@ import java.io.File; public class DownloadService extends Service { private static final String TAG = "DownloadService"; + @Override + public void onCreate() { + super.onCreate(); + Log.e(TAG, "onCreate: "); + Aria.download(this).register(); + //恢复所有未完成的下载任务 + Aria.download(this).resumeAllTask(); + } + @Override public int onStartCommand(Intent intent, int flags, int startId) { startService(new Intent(this, StepService.class)); @@ -37,21 +46,14 @@ public class DownloadService extends Service { startService(new Intent(this, MainService.class)); startService(new Intent(this, ManagerService.class)); startService(new Intent(this, ControlPanelService.class)); - Aria.download(this).register(); - //恢复所有未完成的下载任务 - Aria.download(this).resumeAllTask(); return START_STICKY; } - - @Override - public void onCreate() { - super.onCreate(); - } - @Override public void onDestroy() { super.onDestroy(); + Log.e(TAG, "onDestroy: "); + Aria.download(this).unRegister(); } @Nullable @@ -156,6 +158,7 @@ public class DownloadService extends Service { } Log.e(TAG, "taskFail: " + packageName + "filepath: " + filepath); Aria.download(this).load(task.getDownloadEntity().getId()).cancel(true); + // Aria.download(this) // .load(task.getDownloadEntity().getRealUrl()) //读取下载地址 // .setFilePath(task.getFilePath()) diff --git a/app/src/main/java/com/fuying/sn/service/RemoteService.java b/app/src/main/java/com/fuying/sn/service/RemoteService.java index 94f9e59..e761b02 100644 --- a/app/src/main/java/com/fuying/sn/service/RemoteService.java +++ b/app/src/main/java/com/fuying/sn/service/RemoteService.java @@ -11,14 +11,6 @@ import com.fuying.sn.BuildConfig; import com.fuying.sn.IGetInfoInterface; import com.fuying.sn.config.CommonConfig; import com.fuying.sn.desktop.RunningAppManager; -import com.fuying.sn.network.NetInterfaceManager; -import com.fuying.sn.utils.Utils; -import com.tencent.android.tpush.XGIOperateCallback; -import com.tencent.android.tpush.XGPushConfig; -import com.tencent.android.tpush.XGPushManager; - -import java.util.ArrayList; -import java.util.List; public class RemoteService extends Service { private static final String TAG = "RemoteService"; @@ -36,38 +28,6 @@ public class RemoteService extends Service { public void onCreate() { super.onCreate(); Log.e(TAG, "onCreate: "); - tPushInit(); - } - - private void tPushInit() { - XGPushConfig.enableDebug(this, true); - XGPushManager.registerPush(this, new XGIOperateCallback() { - @Override - public void onSuccess(Object data, int flag) { - //token在设备卸载重装的时候有可能会变 - Log.e("TPush", "注册成功,设备token为:" + data); - List accountInfoList = new ArrayList<>(); - Log.e("TPush", "onSuccess: " + Utils.getSerial()); - accountInfoList.add(new XGPushManager.AccountInfo(XGPushManager.AccountType.CUSTOM.getValue(), Utils.getSerial())); - XGPushManager.upsertAccounts(RemoteService.this, accountInfoList, new XGIOperateCallback() { - @Override - public void onSuccess(Object data, int flag) { - Log.e("TPush", "upsertAccounts onSuccess, data:" + data + ", flag:" + flag); - NetInterfaceManager.getInstance().setPushTags(); - } - - @Override - public void onFail(Object data, int errCode, String msg) { - Log.e("TPush", "upsertAccounts onFail, data:" + data + ", code:" + errCode + ", msg:" + msg); - } - }); - } - - @Override - public void onFail(Object data, int errCode, String msg) { - Log.e("TPush", "注册失败,错误码:" + errCode + ",错误信息:" + msg); - } - }); } @Override diff --git a/app/src/main/java/com/fuying/sn/service/StepService.java b/app/src/main/java/com/fuying/sn/service/StepService.java index b52d7ab..4d9afa5 100644 --- a/app/src/main/java/com/fuying/sn/service/StepService.java +++ b/app/src/main/java/com/fuying/sn/service/StepService.java @@ -17,16 +17,14 @@ import android.content.ServiceConnection; import android.os.Binder; import android.os.Handler; import android.os.IBinder; -import android.os.PowerManager; import android.text.TextUtils; import android.util.Log; import androidx.annotation.Nullable; import com.blankj.utilcode.util.NetworkUtils; -import com.fuying.sn.BuildConfig; import com.fuying.sn.KeepAliveConnection; -import com.fuying.sn.utils.JGYUtils; +import com.fuying.sn.utils.JgyUtils; import com.fuying.sn.utils.ServiceAliveUtils; import com.fuying.sn.utils.Utils; import com.fuying.sn.websocket.JWebSocketClient; @@ -196,7 +194,7 @@ public class StepService extends Service implements NetworkUtils.OnNetworkStatus Log.i("JWebSocketClientService", "websocket连接关闭:" + reason); // client.close(); // initSocketClient(); - if (JGYUtils.getInstance().isScreenOn()) { + if (JgyUtils.getInstance().isScreenOn()) { mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//开启心跳检测 } } @@ -207,7 +205,7 @@ public class StepService extends Service implements NetworkUtils.OnNetworkStatus Log.i("JWebSocketClientService", "websocket连接错误:" + ex.getMessage()); // client.close(); // initSocketClient(); - if (JGYUtils.getInstance().isScreenOn()) { + if (JgyUtils.getInstance().isScreenOn()) { mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//开启心跳检测 } else { Log.i("JWebSocketClientService", "postDelayed off"); @@ -302,7 +300,7 @@ public class StepService extends Service implements NetworkUtils.OnNetworkStatus sendMsg(); } else if (client.isClosed()) { Log.i("JWebSocketClientService", "websocket重连中"); - if (JGYUtils.getInstance().isScreenOn()) { + if (JgyUtils.getInstance().isScreenOn()) { reconnectWs(); } else { Log.i("JWebSocketClientService", "reconnectWs off"); @@ -314,7 +312,7 @@ public class StepService extends Service implements NetworkUtils.OnNetworkStatus initSocketClient(); } //每隔一定的时间,对长连接进行一次心跳检测 - if (JGYUtils.getInstance().isScreenOn()) { + if (JgyUtils.getInstance().isScreenOn()) { mHandler.postDelayed(this, HEART_BEAT_RATE); } else { Log.i("JWebSocketClientService", "websocket息屏不重连"); diff --git a/app/src/main/java/com/fuying/sn/service/main/MainSPresenter.java b/app/src/main/java/com/fuying/sn/service/main/MainSPresenter.java index b37582b..dd61747 100644 --- a/app/src/main/java/com/fuying/sn/service/main/MainSPresenter.java +++ b/app/src/main/java/com/fuying/sn/service/main/MainSPresenter.java @@ -15,7 +15,7 @@ import com.fuying.sn.disklrucache.CacheHelper; import com.fuying.sn.gson.GsonUtils; import com.fuying.sn.network.NetInterfaceManager; import com.fuying.sn.service.ManagerService; -import com.fuying.sn.utils.JGYUtils; +import com.fuying.sn.utils.JgyUtils; import com.fuying.sn.utils.SPUtils; import com.fuying.sn.utils.ServiceAliveUtils; import com.fuying.sn.utils.Utils; @@ -177,7 +177,7 @@ public class MainSPresenter implements MainSContact.Presenter { JsonObject jsonObject = GsonUtils.getJsonObject(jsonString); String ids = jsonObject.get("ids").getAsString(); String packages = jsonObject.get("package").getAsString(); - JGYUtils.getInstance().writeDeselectIDtoSystem(ids, packages); + JgyUtils.getInstance().writeDeselectIDtoSystem(ids, packages); } else { Log.e("getAppInside", "onNext: " + baseResponse.msg); Settings.System.putString(mContext.getContentResolver(), CommonConfig.AOLE_ACTION_APP_FORBID_ID, " "); diff --git a/app/src/main/java/com/fuying/sn/service/main/MainService.java b/app/src/main/java/com/fuying/sn/service/main/MainService.java index 603e7dc..3ae7dcb 100644 --- a/app/src/main/java/com/fuying/sn/service/main/MainService.java +++ b/app/src/main/java/com/fuying/sn/service/main/MainService.java @@ -19,9 +19,6 @@ import android.provider.Settings; import android.text.TextUtils; import android.util.Log; -import com.baidu.location.BDAbstractLocationListener; -import com.baidu.location.BDLocation; -import com.baidu.location.LocationClient; import com.blankj.utilcode.util.NetworkUtils; import com.fuying.sn.BuildConfig; import com.fuying.sn.base.rx.BaseRxService; @@ -39,22 +36,17 @@ import com.fuying.sn.service.GuardService; import com.fuying.sn.service.StepService; import com.fuying.sn.utils.ApkUtils; import com.fuying.sn.utils.CacheUtils; -import com.fuying.sn.utils.JGYUtils; +import com.fuying.sn.utils.JgyUtils; import com.fuying.sn.utils.NetStateUtils; import com.fuying.sn.utils.SPUtils; import com.fuying.sn.utils.TimeUtils; import com.fuying.sn.utils.ToastUtil; import com.fuying.sn.utils.Utils; -import com.tencent.android.tpush.XGIOperateCallback; -import com.tencent.android.tpush.XGPushConfig; -import com.tencent.android.tpush.XGPushManager; import com.tencent.mmkv.MMKV; import com.trello.rxlifecycle4.LifecycleProvider; import com.trello.rxlifecycle4.android.ActivityEvent; import java.io.File; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.TimeUnit; import io.reactivex.rxjava3.core.Observable; @@ -99,7 +91,7 @@ public class MainService extends BaseRxService implements MainSContact.MainView, @Override public void run() { // TODO: 2025/11/11 不确定某些机型状态获取是否正常 - if (JGYUtils.getInstance().isScreenOn()) { + if (JgyUtils.getInstance().isScreenOn()) { Log.e(TAG, "getSnInfo1"); NetInterfaceManager.getInstance().getAppWhiteList(() -> { Log.e("onConnected", "onNext: getAppWhiteList"); @@ -109,7 +101,6 @@ public class MainService extends BaseRxService implements MainSContact.MainView, NetInterfaceManager.getInstance().updateAdminInfo(); NetInterfaceManager.getInstance().SendAppInstallInfo(); SPUtils.put(MainService.this, CommonConfig.JGY_FIRST_BOOT, 1); - tPushInit(); } } }, 15000); @@ -154,7 +145,7 @@ public class MainService extends BaseRxService implements MainSContact.MainView, boolean reboot = mMMKV.decodeBool(CommonConfig.DEVICES_REBOOT, false); Log.e(TAG, "onCreate: reboot = " + reboot); - boolean networkConnected = JGYUtils.getInstance().isNetworkConnected(); + boolean networkConnected = JgyUtils.getInstance().isNetworkConnected(); Log.e(TAG, "onCreate: networkConnected = " + networkConnected); // if (networkConnected && reboot) { Log.e(TAG, "onCreate run: 20秒后请求网络"); @@ -205,7 +196,7 @@ public class MainService extends BaseRxService implements MainSContact.MainView, startService(); Settings.System.putString(getContentResolver(), CommonConfig.APP_SOURCE_WHITE_LIST, DEFAULT_SOURCE); - JGYUtils.getInstance().putBuiltInApps(); + JgyUtils.getInstance().putBuiltInApps(); } private static final String DEFAULT_SOURCE = "com.fuying.sn,com.fuying.appstore,com.fuying.fuxiaoying"; @@ -220,7 +211,7 @@ public class MainService extends BaseRxService implements MainSContact.MainView, ApkUtils.writeAppPackageList(MainService.this, aole_app_forbid); new CacheUtils().cleanApplicationUserData(this, "com.aoleyun.os"); - File file = new File(JGYUtils.getInstance().getDownLoadPath()); + File file = new File(JgyUtils.getInstance().getDownLoadPath()); Log.e(TAG, "versionIsUpdate: " + file.getAbsolutePath()); String[] fileList = file.list(); if (fileList != null) { @@ -247,18 +238,8 @@ public class MainService extends BaseRxService implements MainSContact.MainView, } private void initConfig() { - tPushInit(); // Utils.getPublicIP(MainService.this); - LocationClient locationClient = AmapManager.getInstance().getLocationClient(); - locationClient.stop(); - locationClient.start(); - locationClient.registerLocationListener(new BDAbstractLocationListener() { - @Override - public void onReceiveLocation(BDLocation bdLocation) { - Log.e("initConfig", "onReceiveLocation: "); - locationClient.stop(); - } - }); + AmapManager.getInstance().startLocation(); } private interface ConfigStart { @@ -324,40 +305,9 @@ public class MainService extends BaseRxService implements MainSContact.MainView, // am.setTime(aLong); SystemClock.setCurrentTimeMillis(aLong); Log.e(TAG, "getTimeFromNtpServer: " + aLong); - tPushInit(); } } - private void tPushInit() { - XGPushConfig.enableDebug(this, true); - XGPushManager.registerPush(this, new XGIOperateCallback() { - @Override - public void onSuccess(Object data, int flag) { - //token在设备卸载重装的时候有可能会变 - Log.e("TPush", "注册成功,设备token为:" + data); - List accountInfoList = new ArrayList<>(); - Log.e("TPush", "onSuccess: " + Utils.getSerial()); - accountInfoList.add(new XGPushManager.AccountInfo(XGPushManager.AccountType.CUSTOM.getValue(), Utils.getSerial())); - XGPushManager.upsertAccounts(MainService.this, accountInfoList, new XGIOperateCallback() { - @Override - public void onSuccess(Object data, int flag) { - Log.e("TPush", "upsertAccounts onSuccess, data:" + data + ", flag:" + flag); - NetInterfaceManager.getInstance().setPushTags(); - } - - @Override - public void onFail(Object data, int errCode, String msg) { - Log.e("TPush", "upsertAccounts onFail, data:" + data + ", code:" + errCode + ", msg:" + msg); - } - }); - } - - @Override - public void onFail(Object data, int errCode, String msg) { - Log.e("TPush", "注册失败,错误码:" + errCode + ",错误信息:" + msg); - } - }); - } private void registerReceivers() { registerWiFiReceiver(); diff --git a/app/src/main/java/com/fuying/sn/utils/ApkUtils.java b/app/src/main/java/com/fuying/sn/utils/ApkUtils.java index 47f419e..8847bb3 100644 --- a/app/src/main/java/com/fuying/sn/utils/ApkUtils.java +++ b/app/src/main/java/com/fuying/sn/utils/ApkUtils.java @@ -25,10 +25,11 @@ import android.view.View; import androidx.annotation.RequiresApi; import androidx.core.content.FileProvider; - import com.fuying.sn.BuildConfig; import com.fuying.sn.R; +import com.fuying.sn.bean.AppInfo; import com.fuying.sn.config.CommonConfig; +import com.fuying.sn.gson.GsonUtils; import com.fuying.sn.receiver.InstallResultReceiver; import java.io.BufferedReader; @@ -97,11 +98,7 @@ public class ApkUtils { os.writeBytes("exit\n"); os.flush(); int exitValue = process.waitFor(); - if (exitValue == 0) { - return true; - } else { - return false; - } + return exitValue == 0; } catch (Exception e) { Log.e("*** DEBUG ***", "Unexpected error - Here is what I know: " + e.getMessage()); @@ -419,11 +416,11 @@ public class ApkUtils { Method method; try { activityTherad = Class.forName("android.app.ActivityThread"); - Class paramTypes[] = getParamTypes(activityTherad, "getPackageManager"); + Class[] paramTypes = getParamTypes(activityTherad, "getPackageManager"); method = activityTherad.getMethod("getPackageManager", paramTypes); Object PackageManagerService = method.invoke(activityTherad); pmService = PackageManagerService.getClass(); - Class paramTypes1[] = getParamTypes(pmService, "installPackageAsUser"); + Class[] paramTypes1 = getParamTypes(pmService, "installPackageAsUser"); method = pmService.getMethod("installPackageAsUser", paramTypes1); method.invoke(PackageManagerService, installPath, null, 0x00000040, packageName, getUserId(Binder.getCallingUid()));//getUserId } catch (ClassNotFoundException e) { @@ -629,11 +626,11 @@ public class ApkUtils { Method method; try { activityTherad = Class.forName("android.app.ActivityThread"); - Class paramTypes[] = getParamTypes(activityTherad, "getPackageManager"); + Class[] paramTypes = getParamTypes(activityTherad, "getPackageManager"); method = activityTherad.getMethod("getPackageManager", paramTypes); Object PackageManagerService = method.invoke(activityTherad); pmService = PackageManagerService.getClass(); - Class paramTypes1[] = getParamTypes(pmService, "deletePackageAsUser"); + Class[] paramTypes1 = getParamTypes(pmService, "deletePackageAsUser"); method = pmService.getMethod("deletePackageAsUser", paramTypes1); //getUserId method.invoke(PackageManagerService, packageName, null, getUserId(Binder.getCallingUid()), 0x00000040); @@ -649,7 +646,7 @@ public class ApkUtils { } private static Class[] getParamTypes(Class cls, String mName) { - Class cs[] = null; + Class[] cs = null; Method[] mtd = cls.getMethods(); for (int i = 0; i < mtd.length; i++) { if (!mtd[i].getName().equals(mName)) { @@ -858,9 +855,9 @@ public class ApkUtils { Log.e(TAG, "writeAppPackageList: " + result); // addShortcut(context);//开机之后添加图标到桌面 HashSet factoryAppList = new HashSet<>(); - factoryAppList.addAll(JGYUtils.getInstance().getOwnApp()); - factoryAppList.addAll(JGYUtils.getInstance().getFXYApp()); - factoryAppList.addAll(JGYUtils.getInstance().getAppAndWhite()); + factoryAppList.addAll(JgyUtils.getInstance().getOwnApp()); + factoryAppList.addAll(JgyUtils.getInstance().getFXYApp()); + factoryAppList.addAll(JgyUtils.getInstance().getAppAndWhite()); Log.e("writeAppPackageList", "factoryAppList: " + factoryAppList); if (!TextUtils.isEmpty(result)) { HashSet writeAppSet = new HashSet<>(Arrays.asList(result.split(","))); @@ -950,11 +947,7 @@ public class ApkUtils { for (ResolveInfo info : infos) { hashMap.put(info.activityInfo.packageName, info); } - if (hashMap.get(pkg) == null) { - return false; - } else { - return true; - } + return hashMap.get(pkg) != null; } @@ -982,4 +975,63 @@ public class ApkUtils { return applicationInfos; } + public static boolean isUpdate(Context context, AppInfo appUpdateInfo) { + String packageName = appUpdateInfo.getApp_package(); + long versionCode = appUpdateInfo.getApp_version_code(); + return isUpdate(context, packageName, versionCode); + } + + public static boolean isUpdate(Context context, String packageName, long versionCode) { + PackageInfo packageInfo = null; + try { + packageInfo = context.getPackageManager().getPackageInfo(packageName, 0); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + if (packageInfo == null) { + return true; + } else { + long appVersionCode; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + appVersionCode = packageInfo.getLongVersionCode(); + } else { + appVersionCode = packageInfo.versionCode; + } + if (appVersionCode < versionCode) { + return true; + } else { + Log.e(TAG, "checkUpdate: " + packageName + "\t已经是最新版"); + return false; + } + } + } + + public static void checkAppUpdate(Context context, AppInfo appInfo) { + String packageName = appInfo.getApp_package(); + long versionCode = appInfo.getApp_version_code(); + String url = appInfo.getApp_url(); + PackageInfo packageInfo = null; + try { + packageInfo = context.getPackageManager().getPackageInfo(packageName, 0); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + if (packageInfo == null) { + FileUtils.ariaDownload(context, url, GsonUtils.getJsonObject(GsonUtils.toJSONString(appInfo))); + } else { + long appVersionCode; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + appVersionCode = packageInfo.getLongVersionCode(); + } else { + appVersionCode = packageInfo.versionCode; + } + if (appVersionCode < versionCode) { + FileUtils.ariaDownload(context, url, GsonUtils.getJsonObject(GsonUtils.toJSONString(appInfo))); + } else { + Log.e(TAG, "checkUpdate: " + packageName + "\t已经是最新版"); + } + } + } + + } diff --git a/app/src/main/java/com/fuying/sn/utils/FileUtils.java b/app/src/main/java/com/fuying/sn/utils/FileUtils.java index 8e939f9..d4b17a2 100644 --- a/app/src/main/java/com/fuying/sn/utils/FileUtils.java +++ b/app/src/main/java/com/fuying/sn/utils/FileUtils.java @@ -36,7 +36,7 @@ public class FileUtils { } MessageDigest digest = null; FileInputStream in = null; - byte buffer[] = new byte[1024]; + byte[] buffer = new byte[1024]; int len; try { digest = MessageDigest.getInstance("MD5"); @@ -76,7 +76,7 @@ public class FileUtils { } else { Aria.download(context) .load(url) //读取下载地址 - .setFilePath(JGYUtils.getInstance().getDownLoadPath() + fileName) + .setFilePath(JgyUtils.getInstance().getDownLoadPath() + fileName) .ignoreFilePathOccupy() .setExtendField(jsonObject.toString()) .create(); //启动下载} @@ -85,7 +85,7 @@ public class FileUtils { } else { Aria.download(context) .load(url) //读取下载地址 - .setFilePath(JGYUtils.getInstance().getDownLoadPath() + fileName) + .setFilePath(JgyUtils.getInstance().getDownLoadPath() + fileName) .ignoreFilePathOccupy() .setExtendField(jsonObject.toString()) .create(); //启动下载} diff --git a/app/src/main/java/com/fuying/sn/utils/JGYUtils.java b/app/src/main/java/com/fuying/sn/utils/JgyUtils.java similarity index 97% rename from app/src/main/java/com/fuying/sn/utils/JGYUtils.java rename to app/src/main/java/com/fuying/sn/utils/JgyUtils.java index da79b8b..2447bbc 100644 --- a/app/src/main/java/com/fuying/sn/utils/JGYUtils.java +++ b/app/src/main/java/com/fuying/sn/utils/JgyUtils.java @@ -80,11 +80,11 @@ import io.reactivex.rxjava3.schedulers.Schedulers; import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE; -public class JGYUtils { +public class JgyUtils { private static final String TAG = "JGYUtils"; @SuppressLint("StaticFieldLeak") - private static JGYUtils sInstance; + private static JgyUtils sInstance; private Context mContext; private ContentResolver resolver; private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); @@ -232,7 +232,7 @@ public class JGYUtils { } } - private JGYUtils(Context context) { + private JgyUtils(Context context) { if (context == null) { throw new RuntimeException("Context is NULL"); } @@ -242,11 +242,11 @@ public class JGYUtils { public static void init(Context context) { if (sInstance == null) { - sInstance = new JGYUtils(context); + sInstance = new JgyUtils(context); } } - public static JGYUtils getInstance() { + public static JgyUtils getInstance() { if (sInstance == null) { throw new IllegalStateException("You must be init JGYUtils first"); } @@ -259,17 +259,17 @@ public class JGYUtils { public static boolean isOfficialVersion() { - String channelValue = JGYUtils.getInstance().getStringMetaData(); + String channelValue = JgyUtils.getInstance().getStringMetaData(); return "official".equals(channelValue); } public static boolean isNewlyVersion() { - String channelValue = JGYUtils.getInstance().getStringMetaData(); + String channelValue = JgyUtils.getInstance().getStringMetaData(); return "beta".equals(channelValue); } public static boolean isBetaVersion() { - String channelValue = JGYUtils.getInstance().getStringMetaData(); + String channelValue = JgyUtils.getInstance().getStringMetaData(); return "beta".equals(channelValue); } @@ -611,15 +611,15 @@ public class JGYUtils { } public static String getCustomVersion() { - if (JGYUtils.getInstance().checkAppPlatform() == JGYUtils.ZhanruiPlatform - || JGYUtils.getInstance().checkAppPlatform() == JGYUtils.M40sePlatform - || JGYUtils.getInstance().checkAppPlatform() == JGYUtils.T30ProPlatform - || JGYUtils.getInstance().checkAppPlatform() == JGYUtils.MTK8515Platform - || JGYUtils.getInstance().checkAppPlatform() == JGYUtils.G13Platform - || JGYUtils.getInstance().checkAppPlatform() == JGYUtils.iPlay50SEPlatform - || JGYUtils.getInstance().checkAppPlatform() == JGYUtils.G6Platform - || JGYUtils.getInstance().checkAppPlatform() == JGYUtils.G11JPlatform - || JGYUtils.getInstance().checkAppPlatform() == JGYUtils.G12NLPlatform + if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.ZhanruiPlatform + || JgyUtils.getInstance().checkAppPlatform() == JgyUtils.M40sePlatform + || JgyUtils.getInstance().checkAppPlatform() == JgyUtils.T30ProPlatform + || JgyUtils.getInstance().checkAppPlatform() == JgyUtils.MTK8515Platform + || JgyUtils.getInstance().checkAppPlatform() == JgyUtils.G13Platform + || JgyUtils.getInstance().checkAppPlatform() == JgyUtils.iPlay50SEPlatform + || JgyUtils.getInstance().checkAppPlatform() == JgyUtils.G6Platform + || JgyUtils.getInstance().checkAppPlatform() == JgyUtils.G11JPlatform + || JgyUtils.getInstance().checkAppPlatform() == JgyUtils.G12NLPlatform ) { return getProperty("ro.build.display.id", "获取失败"); } else { @@ -628,8 +628,8 @@ public class JGYUtils { } public static String getRomVersion() { - if (JGYUtils.getInstance().checkAppPlatform() == JGYUtils.ZhanruiPlatform - || JGYUtils.getInstance().checkAppPlatform() == JGYUtils.M40sePlatform) { + if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.ZhanruiPlatform + || JgyUtils.getInstance().checkAppPlatform() == JgyUtils.M40sePlatform) { return getProperty("ro.build.id", "获取失败"); } else { return getProperty("ro.build.display.id", "获取失败"); @@ -854,7 +854,7 @@ public class JGYUtils { UserHandle user = Process.myUserHandle(); Log.i("settingssssssstemf", (add ? "Adding" : "Removing") + " package as role holder, role: " + roleName + ", package: " + packageName); - if (JGYUtils.getInstance().checkAppPlatform() != JGYUtils.MTKPlatform) { + if (JgyUtils.getInstance().checkAppPlatform() != JgyUtils.MTKPlatform) { RoleManager roleManager = context.getSystemService(RoleManager.class); Executor executor = context.getMainExecutor(); Consumer callback = successful -> { @@ -953,7 +953,7 @@ public class JGYUtils { Intent intent = new Intent("setDefaultLauncher"); intent.putExtra("package", pkg); intent.putExtra("className", className); - if (JGYUtils.getInstance().checkAppPlatform() == MTKPlatform) { + if (JgyUtils.getInstance().checkAppPlatform() == MTKPlatform) { Log.e(TAG, "setDefaultDesktop: MTK"); //爱华定制 intent.setComponent(new ComponentName("com.android.settings", "com.android.settings.AoleReceiver")); diff --git a/app/src/main/java/com/fuying/sn/utils/Utils.java b/app/src/main/java/com/fuying/sn/utils/Utils.java index f2aed6c..99cdcaa 100644 --- a/app/src/main/java/com/fuying/sn/utils/Utils.java +++ b/app/src/main/java/com/fuying/sn/utils/Utils.java @@ -304,14 +304,14 @@ public class Utils { return weeks[week_index]; } - // 非空判断 - public static boolean isEmpty(String s) { - if (null == s) - return true; - if (s.length() == 0) - return true; - return s.trim().length() == 0; - } +// // 非空判断 +// public static boolean isEmpty(String s) { +// if (null == s) +// return true; +// if (s.length() == 0) +// return true; +// return s.trim().length() == 0; +// } // 手动隐藏键盘 public static void CloseKeyBoard(Context context) { @@ -604,12 +604,12 @@ public class Utils { * @return */ public static String getSerial() { - if (JGYUtils.getInstance().checkAppPlatform() == JGYUtils.G13Platform - || JGYUtils.getInstance().checkAppPlatform() == JGYUtils.iPlay50SEPlatform + if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.G13Platform + || JgyUtils.getInstance().checkAppPlatform() == JgyUtils.iPlay50SEPlatform ) { return getSn(); } else { - return JGYUtils.getInstance().getIMEI(); + return JgyUtils.getInstance().getIMEI(); } } @@ -1102,10 +1102,21 @@ public class Utils { ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); activityManager.getMemoryInfo(memoryInfo); // 当前系统可用内存 ,将获得的内存大小规格化 - + Log.e(TAG, "getAvailMemory: " + memoryInfo.availMem); return memoryInfo.availMem; } + public static long getTotalMem(Context context) { + // 获取android当前可用内存大小 + ActivityManager activityManager = (ActivityManager) context + .getSystemService(Context.ACTIVITY_SERVICE); + ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); + activityManager.getMemoryInfo(memoryInfo); + // 当前系统可用内存 ,将获得的内存大小规格化 + Log.e(TAG, "getTotalMem: " + memoryInfo.totalMem); + return memoryInfo.totalMem; + } + /** * 描述:总内存. * @@ -1199,8 +1210,8 @@ public class Utils { String imei = getIMEI(context); Log.e(TAG, "getMachine: " + imei); String system_version = Build.VERSION.RELEASE; - String firmware_version = JGYUtils.getRomVersion(); - String rom = JGYUtils.getCustomVersion(); + String firmware_version = JgyUtils.getRomVersion(); + String rom = JgyUtils.getCustomVersion(); String screen_rate = getAndroiodScreenProperty(context); JsonObject jsonObject = new JsonObject(); @@ -1237,7 +1248,7 @@ public class Utils { jsonObject.addProperty("memory", memory); jsonObject.addProperty("mac", getMAC(context)); jsonObject.addProperty("storage", storage); - jsonObject.addProperty("is_wifi", JGYUtils.getInstance().isWifiConnect()); + jsonObject.addProperty("is_wifi", JgyUtils.getInstance().isWifiConnect()); jsonObject.addProperty("CPU", CPU + "核"); jsonObject.addProperty("use_space", use_space); jsonObject.addProperty("use_ram", use_ram); diff --git a/app/src/main/res/drawable-hdpi/icon_blue_back.png b/app/src/main/res/drawable-hdpi/icon_blue_back.png new file mode 100644 index 0000000..aadbdb9 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_blue_back.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_close.png b/app/src/main/res/drawable-hdpi/icon_close.png new file mode 100644 index 0000000..9ebcb0b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_close.png differ diff --git a/app/src/main/res/drawable-hdpi/main_background.png b/app/src/main/res/drawable-hdpi/main_background.png new file mode 100644 index 0000000..6b3ee89 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/main_background.png differ diff --git a/app/src/main/res/drawable/bt_normnl.xml b/app/src/main/res/drawable/bt_normnl.xml index 5d03ac7..ff271d5 100644 --- a/app/src/main/res/drawable/bt_normnl.xml +++ b/app/src/main/res/drawable/bt_normnl.xml @@ -2,8 +2,7 @@ - + - + - + diff --git a/app/src/main/res/drawable/dialog_background.xml b/app/src/main/res/drawable/dialog_background.xml new file mode 100644 index 0000000..4937102 --- /dev/null +++ b/app/src/main/res/drawable/dialog_background.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/app/src/main/res/drawable/radio_checked.xml b/app/src/main/res/drawable/radio_checked.xml index 341dbca..c351730 100644 --- a/app/src/main/res/drawable/radio_checked.xml +++ b/app/src/main/res/drawable/radio_checked.xml @@ -2,8 +2,7 @@ - + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/update_cancel_background.xml b/app/src/main/res/drawable/update_cancel_background.xml new file mode 100644 index 0000000..b33e68e --- /dev/null +++ b/app/src/main/res/drawable/update_cancel_background.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml index fed34c1..9437779 100644 --- a/app/src/main/res/layout/activity_home.xml +++ b/app/src/main/res/layout/activity_home.xml @@ -1,7 +1,79 @@ - - - \ No newline at end of file + xmlns:tools="http://schemas.android.com/tools" + tools:context=".activity.home.HomeActivity"> + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_selecte_grade.xml b/app/src/main/res/layout/activity_selecte_grade.xml index 5a96dec..d278a44 100644 --- a/app/src/main/res/layout/activity_selecte_grade.xml +++ b/app/src/main/res/layout/activity_selecte_grade.xml @@ -238,7 +238,7 @@ android:layout_height="wrap_content" android:layout_marginTop="24dp" android:text="@string/hint" - android:textColor="@color/activation_color" /> + android:textColor="@color/default_blue" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_device.xml b/app/src/main/res/layout/fragment_device.xml new file mode 100644 index 0000000..ba9abaa --- /dev/null +++ b/app/src/main/res/layout/fragment_device.xml @@ -0,0 +1,648 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_dialog_restart.xml b/app/src/main/res/layout/fragment_dialog_restart.xml index 4f2a583..e8d4297 100644 --- a/app/src/main/res/layout/fragment_dialog_restart.xml +++ b/app/src/main/res/layout/fragment_dialog_restart.xml @@ -89,7 +89,7 @@ android:gravity="center" android:onClick="@{click::restart}" android:text="确定" - android:textColor="@color/activation_color" + android:textColor="@color/default_blue" android:textSize="@dimen/sp_11" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="@+id/tv_content" diff --git a/app/src/main/res/layout/fragment_usage.xml b/app/src/main/res/layout/fragment_usage.xml new file mode 100644 index 0000000..30951a2 --- /dev/null +++ b/app/src/main/res/layout/fragment_usage.xml @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index dcb66d7..328a759 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -7,17 +7,258 @@ - #ffffff - #000000 - #80808080 - #D3D3D3 - #CD000000 #D3D3D3 - #4880ff - + #4880ff #E5000000 - #9a9a9a + #000000 + #000000 + #000000 + #d3d3d3 + + + + #00000000 + #FFE2C59B + #FFFFFFF0 + #FFFFFFE0 + #FFFFFF00 + #FFFFFAFA + #FFFFFAF0 + #FFFFFACD + #FFFFF8DC + #FFFFF5EE + #FFFFF0F5 + #FFFFEFD5 + #FFFFEBCD + #FFFFE4E1 + #FFFFE4C4 + #FFFFE4B5 + #FFFFDEAD + #FFFFDAB9 + #FFFFD700 + #FFFFC0CB + #FFFFB6C1 + #FFFFA500 + #FFFFA07A + #FFFF8C00 + #FFFF7F50 + #FFFF69B4 + #FFFF6347 + #FFFF4500 + #FFFF1493 + #FFFF00FF + #FFFF0000 + #FFFDF5E6 + #FFFAFAD2 + #FFFAF0E6 + #FFFAEBD7 + #FFFA8072 + #FFF8F8FF + #FFF5FFFA + #FFF5F5F5 + #FFF5F5DC + #FFF5DEB3 + #FFF4A460 + #FFF0FFFF + #FFF0F8FF + #FFF0E68C + #FFF08080 + #FFEEE8AA + #FFEE82EE + #FFE9967A + #FFE6E6FA + #FFE0FFFF + #FFDEB887 + #FFDDA0DD + #FFDCDCDC + #FFDC143C + #FFDB7093 + #FFDAA520 + #FFDA70D6 + #FFD8BFD8 + #FFD3D3D3 + #FFD2B48C + #FFD2691E + #FFCD853F + #FFCD5C5C + #FFC71585 + #FFC0C0C0 + #FFBDB76B + #FFBC8F8F + #FFBA55D3 + #FFB8860B + #FFB22222 + #FFB0E0E6 + #FFB0C4DE + #FFAFEEEE + #FFADFF2F + #FFADD8E6 + #FFA9A9A9 + #FFA52A2A + #FFA0522D + #FF9932CC + #FF98FB98 + #FF9400D3 + #FF9370DB + #FF90EE90 + #FF8FBC8F + #FF8B4513 + #FF8B008B + #FF8B0000 + #FF8A2BE2 + #FF87CEFA + #FF87CEEB + #FF808080 + #FF808000 + #FF800080 + #FF800000 + #FF7FFFD4 + #FF7FFF00 + #FF7CFC00 + #FF7B68EE + #FF778899 + #FF708090 + #FF6B8E23 + #FF6A5ACD + #FF696969 + #FF66CDAA + #FF6495ED + #FF5F9EA0 + #FF556B2F + #FF4B0082 + #FF48D1CC + #FF483D8B + #FF4682B4 + #FF4169E1 + #FF40E0D0 + #FF3CB371 + #FF32CD32 + #FF2F4F4F + #FF2E8B57 + #FF228B22 + #FF20B2AA + #FF1E90FF + #FF191970 + #FF00FFFF + #FF00FF7F + #FF00FF00 + #FF00FA9A + #FF00CED1 + #FF00BFFF + #FF008B8B + #FF008080 + #FF008000 + #FF006400 + #FF0000FF + #FF0000CD + #FF00008B + #FF000080 + #FF2B2B2B + + + #ffffff + #ffffe0 + #fffaf0 + #fffacd + #fff8dc + #fff5ee + #fff0f5 + #ffefd5 + #ffebcd + #ffe4e1 + #ffdead + #ffdab9 + #ffb6c1 + #ffa07a + #ff8c00 + #ff69b4 + #ff4500 + #ff1493 + #ff00ff + #fdf5e6 + #fafad2 + #faebd7 + #f8f8ff + #f5fffa + #f5f5f5 + #f4a460 + #f0fff0 + #f0f8ff + #f08080 + #eee8aa + #e9967a + #e0ffff + #deb887 + #dcdcdc + #db7093 + #d3d3d3 + #d3d3d3 + #cd5c5c + #c71585 + #bdb76b + #bc8f8f + #ba55d3 + #b8860b + #b0e0e6 + #b0c4de + #afeeee + #adff2f + #add8e6 + #a9a9a9 + #a9a9a9 + #9932cc + #98fb98 + #9400d3 + #9370db + #90ee90 + #8fbc8f + #8b4513 + #8b008b + #8b0000 + #8a2be2 + #87cefa + #87ceeb + #808080 + #7cfc00 + #7b68ee + #778899 + #778899 + #708090 + #708090 + #6b8e23 + #6a5acd + #696969 + #696969 + #66cdaa + #6495ed + #5f9ea0 + #556b2f + #48d1cc + #483d8b + #4682b4 + #4169e1 + #3cb371 + #32cd32 + #2f4f4f + #2f4f4f + #2e8b57 + #228b22 + #20b2aa + #1e90ff + #191970 + #00ffff + #00ff7f + #00fa9a + #00ced1 + #00bfff + #008b8b + #006400 + #0000cd + #00008b + #000000 + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 5022e6c..2be8bd1 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -66,4 +66,25 @@ true + diff --git a/app/tpns-configs.json b/app/tpns-configs.json deleted file mode 100644 index 81f3138..0000000 --- a/app/tpns-configs.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "tpns": { - "access_id": "1500031216", - "access_key": "A1HBG2922B9Z" - }, - "com.fuying.sn": { - "channel": { - "enable": true - } - }, - "debug": false, - "version": "1.4.3.4", - "upgrade": false -} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 0538901..56b0369 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,6 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:3.6.4' - classpath "com.tencent.android.tpns:tpnsplugin:1.8.0" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/settings.gradle b/settings.gradle index f8118b6..5968770 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,2 @@ -include ':app' +include ':app', ':FlycoTabLayoutZ_Lib' rootProject.name='FLY我的设备'