add ui manager & add a custom dynamic island

This commit is contained in:
Tungstend 2022-11-03 21:42:23 +08:00
parent b9f46f6cca
commit 81816b12a2
9 changed files with 347 additions and 16 deletions

View File

@ -6,14 +6,20 @@ import androidx.constraintlayout.widget.ConstraintLayout;
import com.google.android.material.tabs.TabLayout;
import com.tungsten.fcl.R;
import com.tungsten.fcl.ui.UIManager;
import com.tungsten.fcllibrary.component.FCLActivity;
import com.tungsten.fcllibrary.component.theme.ThemeEngine;
import com.tungsten.fcllibrary.component.view.FCLDynamicIsland;
import com.tungsten.fcllibrary.component.view.FCLTitleView;
import com.tungsten.fcllibrary.component.view.FCLUILayout;
public class MainActivity extends FCLActivity implements TabLayout.OnTabSelectedListener {
public ConstraintLayout background;
private FCLTitleView titleView;
private FCLDynamicIsland titleView;
private UIManager uiManager;
private FCLUILayout uiLayout;
private TabLayout tabLayout;
@ -26,6 +32,11 @@ public class MainActivity extends FCLActivity implements TabLayout.OnTabSelected
background.setBackground(ThemeEngine.getInstance().getTheme().getBackground(this));
titleView = findViewById(R.id.title);
uiLayout = findViewById(R.id.ui_layout);
uiManager = new UIManager(this, uiLayout);
uiManager.init();
tabLayout = findViewById(R.id.tab_layout);
tabLayout.addOnTabSelectedListener(this);
tabLayout.selectTab(tabLayout.getTabAt(3));
@ -38,25 +49,26 @@ public class MainActivity extends FCLActivity implements TabLayout.OnTabSelected
public void onTabSelected(TabLayout.Tab tab) {
switch (tab.getPosition()) {
case 0:
titleView.setTitle(getString(R.string.account));
titleView.setTextWithAnim(getString(R.string.account));
break;
case 1:
titleView.setTitle(getString(R.string.version));
titleView.setTextWithAnim(getString(R.string.version));
break;
case 2:
titleView.setTitle(getString(R.string.install));
titleView.setTextWithAnim(getString(R.string.install));
break;
case 4:
titleView.setTitle(getString(R.string.download));
titleView.setTextWithAnim(getString(R.string.download));
break;
case 5:
titleView.setTitle(getString(R.string.multiplayer));
titleView.setTextWithAnim(getString(R.string.multiplayer));
break;
case 6:
titleView.setTitle(getString(R.string.setting));
titleView.setTextWithAnim(getString(R.string.setting));
break;
default:
titleView.setTitle(getString(R.string.app_name));
titleView.setTextWithAnim(getString(R.string.app_name));
uiManager.switchUI(uiManager.getMainUI());
break;
}
}

View File

@ -0,0 +1,4 @@
package com.tungsten.fcl.ui;
public class ChildUIManager {
}

View File

@ -0,0 +1,79 @@
package com.tungsten.fcl.ui;
import android.content.Context;
import com.tungsten.fcl.R;
import com.tungsten.fcl.ui.main.MainUI;
import com.tungsten.fclcore.util.Logging;
import com.tungsten.fcllibrary.component.ui.FCLBaseUI;
import com.tungsten.fcllibrary.component.view.FCLUILayout;
import java.util.logging.Level;
public class UIManager {
private static UIManager instance;
public static UIManager getInstance() {
if (instance == null) {
throw new IllegalStateException("UIManager not initialized!");
}
return instance;
}
private final Context context;
private final FCLUILayout parent;
private MainUI mainUI;
private FCLBaseUI[] allUIs;
private FCLBaseUI currentUI;
public UIManager(Context context, FCLUILayout parent) {
this.context = context;
this.parent = parent;
}
public void init() {
if (instance != null) {
Logging.LOG.log(Level.WARNING, "UIManager already initialized!");
return;
}
instance = this;
mainUI = new MainUI(context, parent, R.layout.ui_main);
allUIs = new FCLBaseUI[] {
mainUI
};
}
public Context getContext() {
return context;
}
public FCLUILayout getParent() {
return parent;
}
public MainUI getMainUI() {
return mainUI;
}
public FCLBaseUI getCurrentUI() {
return currentUI;
}
public void switchUI(FCLBaseUI ui) {
for (FCLBaseUI baseUI : allUIs) {
if (ui == baseUI) {
if (currentUI != null) {
currentUI.onStop();
}
ui.onStart();
currentUI = ui;
break;
}
}
}
}

View File

@ -0,0 +1,18 @@
package com.tungsten.fcl.ui.main;
import android.content.Context;
import com.tungsten.fcllibrary.component.ui.FCLCommonUI;
import com.tungsten.fcllibrary.component.view.FCLUILayout;
public class MainUI extends FCLCommonUI {
public MainUI(Context context, FCLUILayout parent, int id) {
super(context, parent, id);
}
@Override
public void refresh() {
}
}

View File

@ -7,16 +7,19 @@
android:id="@+id/background"
tools:context=".activity.MainActivity">
<com.tungsten.fcllibrary.component.view.FCLTitleView
android:id="@+id/title"
app:title="@string/app_name"
android:layout_width="0dp"
<com.tungsten.fcllibrary.component.view.FCLUILayout
android:id="@+id/ui_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/bottom_split"/>
<com.tungsten.fcllibrary.component.view.FCLDynamicIsland
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintVertical_bias="0"
app:layout_constraintWidth_percent="0.75"
app:layout_constraintHeight_percent="0.10"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,92 @@
package com.tungsten.fcllibrary.anim;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import com.tungsten.fcllibrary.component.view.FCLDynamicIsland;
public class DynamicIslandAnim {
private final FCLDynamicIsland view;
private ObjectAnimator expandScaleAnimatorX;
private ObjectAnimator shrinkScaleAnimatorX;
private ObjectAnimator expandScaleAnimatorY;
private ObjectAnimator shrinkScaleAnimatorY;
private ObjectAnimator expandAdjustAnimatorX;
private ObjectAnimator shrinkAdjustAnimatorX;
private ObjectAnimator expandAdjustAnimatorY;
private ObjectAnimator shrinkAdjustAnimatorY;
public DynamicIslandAnim(FCLDynamicIsland view) {
this.view = view;
}
public void refresh(float scale) {
if (expandScaleAnimatorX != null && expandScaleAnimatorX.isRunning()) {
expandScaleAnimatorX.cancel();
}
if (shrinkScaleAnimatorX != null && shrinkScaleAnimatorX.isRunning()) {
shrinkScaleAnimatorX.cancel();
}
if (expandScaleAnimatorY != null && expandScaleAnimatorY.isRunning()) {
expandScaleAnimatorY.cancel();
}
if (shrinkScaleAnimatorY != null && shrinkScaleAnimatorY.isRunning()) {
shrinkScaleAnimatorY.cancel();
}
if (expandAdjustAnimatorX != null && expandAdjustAnimatorX.isRunning()) {
expandAdjustAnimatorX.cancel();
}
if (shrinkAdjustAnimatorX != null && shrinkAdjustAnimatorX.isRunning()) {
shrinkAdjustAnimatorX.cancel();
}
if (expandAdjustAnimatorY != null && expandAdjustAnimatorY.isRunning()) {
expandAdjustAnimatorY.cancel();
}
if (shrinkAdjustAnimatorY != null && shrinkAdjustAnimatorY.isRunning()) {
shrinkAdjustAnimatorY.cancel();
}
expandScaleAnimatorX = ObjectAnimator.ofFloat(view, "scaleX", scale, 0.95f).setDuration(200);
shrinkScaleAnimatorX = ObjectAnimator.ofFloat(view, "scaleX", 0.95f, scale).setDuration(200);
expandScaleAnimatorY = ObjectAnimator.ofFloat(view, "scaleY", 0.95f, 0.95f).setDuration(200);
shrinkScaleAnimatorY = ObjectAnimator.ofFloat(view, "scaleY", 0.95f, 0.95f).setDuration(200);
expandAdjustAnimatorX = ObjectAnimator.ofFloat(view, "scaleX", 0.95f, 1f).setDuration(200);
shrinkAdjustAnimatorX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.95f).setDuration(200);
expandAdjustAnimatorY = ObjectAnimator.ofFloat(view, "scaleY", 0.95f, 1f).setDuration(200);
shrinkAdjustAnimatorY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.95f).setDuration(200);
}
public void run(String text) {
shrinkScaleAnimatorX.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
view.refresh(text);
view.post(() -> {
expandScaleAnimatorX.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
expandAdjustAnimatorX.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
shrinkAdjustAnimatorX.start();
shrinkAdjustAnimatorY.start();
}
});
expandAdjustAnimatorX.start();
expandAdjustAnimatorY.start();
}
});
expandScaleAnimatorX.start();
expandScaleAnimatorY.start();
});
}
});
shrinkScaleAnimatorX.start();
shrinkScaleAnimatorY.start();
}
}

View File

@ -18,6 +18,7 @@ public abstract class FCLCommonUI extends FCLBaseUI {
super(context);
setContentView(id);
this.parent = parent;
onCreate();
}
@Override

View File

@ -0,0 +1,116 @@
package com.tungsten.fcllibrary.component.view;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.Gravity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
import com.tungsten.fcllibrary.anim.DynamicIslandAnim;
import com.tungsten.fcllibrary.component.theme.ThemeEngine;
import com.tungsten.fcllibrary.util.ConvertUtils;
public class FCLDynamicIsland extends AppCompatTextView {
DynamicIslandAnim anim;
private Path outlinePath;
private Paint outlinePaint;
private Paint insidePaint;
private Paint textPaint;
private final Runnable runnable = () -> {
outlinePaint.setAntiAlias(true);
outlinePaint.setColor(ThemeEngine.getInstance().getTheme().getDkColor());
outlinePaint.setStyle(Paint.Style.STROKE);
outlinePaint.setStrokeWidth(ConvertUtils.dip2px(getContext(), 3));
insidePaint.setAntiAlias(true);
insidePaint.setColor(ThemeEngine.getInstance().getTheme().getColor());
insidePaint.setStyle(Paint.Style.FILL);
textPaint.setAntiAlias(true);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(56);
textPaint.setColor(ThemeEngine.getInstance().getTheme().getAutoTint());
textPaint.setTextAlign(Paint.Align.CENTER);
invalidate();
setTextColor(ThemeEngine.getInstance().getTheme().getAutoTint());
};
private void init() {
anim = new DynamicIslandAnim(this);
setGravity(Gravity.CENTER);
int tb = ConvertUtils.dip2px(getContext(), 8f);
int lr = ConvertUtils.dip2px(getContext(), 18f);
setPadding(lr, tb, lr, tb);
outlinePath = new Path();
outlinePaint = new Paint();
insidePaint = new Paint();
textPaint = new Paint();
outlinePaint.setAntiAlias(true);
outlinePaint.setColor(ThemeEngine.getInstance().getTheme().getDkColor());
outlinePaint.setStyle(Paint.Style.STROKE);
outlinePaint.setStrokeWidth(ConvertUtils.dip2px(getContext(), 3));
insidePaint.setAntiAlias(true);
insidePaint.setColor(ThemeEngine.getInstance().getTheme().getColor());
insidePaint.setStyle(Paint.Style.FILL);
textPaint.setAntiAlias(true);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(56);
textPaint.setColor(ThemeEngine.getInstance().getTheme().getAutoTint());
textPaint.setTextAlign(Paint.Align.CENTER);
}
public FCLDynamicIsland(@NonNull Context context) {
super(context);
init();
ThemeEngine.getInstance().registerEvent(this, runnable);
}
public FCLDynamicIsland(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
ThemeEngine.getInstance().registerEvent(this, runnable);
}
public FCLDynamicIsland(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
ThemeEngine.getInstance().registerEvent(this, runnable);
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float offset = ConvertUtils.dip2px(getContext(), 1.5f);
float width = getMeasuredWidth() - 2 * offset;
float height = getMeasuredHeight() - 2 * offset;
outlinePath = new Path();
outlinePath.moveTo(offset + (height / 2), offset);
outlinePath.arcTo(offset, offset, offset + height, offset + height, 270, -180, false);
outlinePath.lineTo(offset + width - (height / 2), height + offset);
outlinePath.arcTo(offset + width - height, offset, width + offset, height + offset, 90, -180, false);
outlinePath.lineTo(offset + (height / 2), offset);
canvas.drawPath(outlinePath, insidePaint);
canvas.drawPath(outlinePath, outlinePaint);
canvas.drawText(getText().toString(), (int) (getWidth() / 2), (int) (getHeight() / 2) + 21, textPaint);
}
public void refresh(String text) {
setText(text);
invalidate();
}
public void setTextWithAnim(String text) {
post(() -> {
anim.refresh((float) getMeasuredHeight() / (float) getMeasuredWidth());
anim.run(text);
});
}
}