This commit is contained in:
Zhanghu
2025-09-11 18:27:44 +08:00
parent 637867ade8
commit db4f4c7955
14 changed files with 350 additions and 173 deletions

View File

@@ -41,6 +41,7 @@ dependencies {
implementation libs.material
implementation libs.activity
implementation libs.constraintlayout
implementation libs.preference
testImplementation libs.junit
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core

View File

@@ -1,13 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Dashboard">
android:theme="@style/Theme.Dashboard"
android:usesCleartextTraffic="true">
<activity
android:name=".SettingsActivity"
android:exported="false"
android:label="@string/title_activity_settings" />
<activity
android:name=".BuildingDashboardActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
@@ -26,7 +33,7 @@
<activity
android:name=".GalleryActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:exported="true"></activity>
android:exported="true" />
<receiver
android:name=".BootBroadcastReceiver"

View File

@@ -1,25 +1,24 @@
package cn.ykbox.dashboard;
import android.annotation.SuppressLint;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Build;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowInsets;
import android.webkit.WebViewClient;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.preference.PreferenceManager;
import cn.ykbox.dashboard.databinding.ActivityBuildingDashboardBinding;
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*/
public class BuildingDashboardActivity extends AppCompatActivity {
public class BuildingDashboardActivity extends FullscreenActivity {
private final static String TAG = "DashboardActivity";
/**
* Whether or not the system UI should be auto-hidden after
* {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
@@ -32,53 +31,6 @@ public class BuildingDashboardActivity extends AppCompatActivity {
*/
private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
/**
* Some older devices needs a small delay between UI widget updates
* and a change of the status and navigation bar.
*/
private static final int UI_ANIMATION_DELAY = 300;
private final Handler mHideHandler = new Handler(Looper.myLooper());
private View mContentView;
private final Runnable mHidePart2Runnable = new Runnable() {
@SuppressLint("InlinedApi")
@Override
public void run() {
// Delayed removal of status and navigation bar
if (Build.VERSION.SDK_INT >= 30) {
mContentView.getWindowInsetsController().hide(
WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
} else {
// Note that some of these constants are new as of API 16 (Jelly Bean)
// and API 19 (KitKat). It is safe to use them, as they are inlined
// at compile-time and do nothing on earlier devices.
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
}
};
private View mControlsView;
private final Runnable mShowPart2Runnable = new Runnable() {
@Override
public void run() {
// Delayed display of UI elements
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.show();
}
mControlsView.setVisibility(View.VISIBLE);
}
};
private boolean mVisible;
private final Runnable mHideRunnable = new Runnable() {
@Override
public void run() {
hide();
}
};
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
@@ -103,86 +55,65 @@ public class BuildingDashboardActivity extends AppCompatActivity {
}
};
private ActivityBuildingDashboardBinding binding;
/// ActivityResultLauncher 用于处理设置页面的返回结果
private ActivityResultLauncher<Intent> settingsLauncher;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityBuildingDashboardBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
mVisible = true;
mControlsView = binding.fullscreenContentControls;
mContentView = binding.fullscreenContent;
super.setViews(binding.webview, binding.fullscreenContentControls);
super.onCreate(savedInstanceState);
// Set up the user interaction to manually show or hide the system UI.
mContentView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
toggle();
}
});
// 初始化 ActivityResultLauncher
initSettingsLauncher();
setupWebView();
// Upon interacting with UI controls, delay any scheduled hide()
// operations to prevent the jarring behavior of controls going away
// while interacting with the UI.
binding.dummyButton.setOnTouchListener(mDelayHideTouchListener);
binding.settingsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 打开设置界面
openSettingsActivity();
}
});
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
protected void onResume() {
super.onResume();
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
delayedHide(100);
}
private void toggle() {
if (mVisible) {
hide();
} else {
show();
}
}
private void hide() {
// Hide UI first
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.hide();
}
mControlsView.setVisibility(View.GONE);
mVisible = false;
// Schedule a runnable to remove the status and navigation bar after a delay
mHideHandler.removeCallbacks(mShowPart2Runnable);
mHideHandler.postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY);
}
private void show() {
// Show the system bar
if (Build.VERSION.SDK_INT >= 30) {
mContentView.getWindowInsetsController().show(
WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
} else {
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
mVisible = true;
// Schedule a runnable to display UI elements after a delay
mHideHandler.removeCallbacks(mHidePart2Runnable);
mHideHandler.postDelayed(mShowPart2Runnable, UI_ANIMATION_DELAY);
SharedPreferences pre = PreferenceManager.getDefaultSharedPreferences(this);
String url = pre.getString("k_url", "http://10.1.58.176:8002");
binding.webview.loadUrl(url); // 加载网页
}
/**
* Schedules a call to hide() in delay milliseconds, canceling any
* previously scheduled calls.
* 初始化设置页面的 ActivityResultLauncher
*/
private void delayedHide(int delayMillis) {
mHideHandler.removeCallbacks(mHideRunnable);
mHideHandler.postDelayed(mHideRunnable, delayMillis);
private void initSettingsLauncher() {
settingsLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
}
);
}
/**
* 打开设置页面
*/
private void openSettingsActivity() {
Intent intent = new Intent(this, SettingsActivity.class);
settingsLauncher.launch(intent);
}
private void setupWebView() {
binding.webview.getSettings().setJavaScriptEnabled(true); // 启用 JavaScript
binding.webview.setWebViewClient(new WebViewClient()); // 防止跳转到外部浏览器
}
}

View File

@@ -1,34 +0,0 @@
package cn.ykbox.dashboard;
import java.util.ArrayList;
import java.util.List;
public class DataBean {
public Integer imageRes;
public String imageUrl;
public String title;
public int viewType;
public DataBean(Integer imageRes, String title, int viewType) {
this.imageRes = imageRes;
this.title = title;
this.viewType = viewType;
}
public DataBean(String imageUrl, String title, int viewType) {
this.imageUrl = imageUrl;
this.title = title;
this.viewType = viewType;
}
public static List<DataBean> getTestData() {
List<DataBean> list = new ArrayList<>();
list.add(new DataBean(R.drawable.image1, "第3代无线智能中控", 1));
list.add(new DataBean(R.drawable.image2, "智慧班牌", 3));
list.add(new DataBean(R.drawable.image3, "无线话筒", 3));
list.add(new DataBean(R.drawable.image4, "可移动式智能讲桌", 1));
list.add(new DataBean(R.drawable.image5, "TD2+智慧屏集成讲桌", 1));
list.add(new DataBean(R.drawable.image6, "TD5+智慧屏集成讲台", 3));
return list;
}
}

View File

@@ -0,0 +1,160 @@
package cn.ykbox.dashboard;
import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowInsets;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
public class FullscreenActivity extends AppCompatActivity {
private final static String TAG = "FullscreenActivity";
/**
* Some older devices needs a small delay between UI widget updates
* and a change of the status and navigation bar.
*/
private static final int UI_ANIMATION_DELAY = 300;
private final Handler mHideHandler = new Handler(Looper.myLooper());
private View mContentView;
private final Runnable mHidePart2Runnable = new Runnable() {
@SuppressLint("InlinedApi")
@Override
public void run() {
// Delayed removal of status and navigation bar
if (Build.VERSION.SDK_INT >= 30) {
mContentView.getWindowInsetsController().hide(
WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
} else {
// Note that some of these constants are new as of API 16 (Jelly Bean)
// and API 19 (KitKat). It is safe to use them, as they are inlined
// at compile-time and do nothing on earlier devices.
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
}
};
private View mControlsView;
private final Runnable mShowPart2Runnable = new Runnable() {
@Override
public void run() {
// Delayed display of UI elements
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.show();
}
mControlsView.setVisibility(View.VISIBLE);
}
};
private boolean mVisible;
private final Runnable mHideRunnable = new Runnable() {
@Override
public void run() {
hide();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mVisible = true;
// Set up the user interaction to manually show or hide the system UI.
// mContentView.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View view) {
// toggle();
// }
// });
mContentView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
toggle();
break;
case MotionEvent.ACTION_UP:
view.performClick();
break;
default:
break;
}
return false;
}
});
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
delayedHide(100);
}
private void toggle() {
Log.d(TAG, "toggle, mVisible=" + mVisible);
if (mVisible) {
hide();
} else {
show();
delayedHide(30000);
}
}
private void hide() {
// Hide UI first
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.hide();
}
mControlsView.setVisibility(View.GONE);
mVisible = false;
// Schedule a runnable to remove the status and navigation bar after a delay
mHideHandler.removeCallbacks(mShowPart2Runnable);
mHideHandler.postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY);
}
private void show() {
// Show the system bar
if (Build.VERSION.SDK_INT >= 30) {
mContentView.getWindowInsetsController().show(
WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
} else {
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
mVisible = true;
// Schedule a runnable to display UI elements after a delay
mHideHandler.removeCallbacks(mHidePart2Runnable);
mHideHandler.postDelayed(mShowPart2Runnable, UI_ANIMATION_DELAY);
}
/**
* Schedules a call to hide() in delay milliseconds, canceling any
* previously scheduled calls.
*/
protected void delayedHide(int delayMillis) {
mHideHandler.removeCallbacks(mHideRunnable);
mHideHandler.postDelayed(mHideRunnable, delayMillis);
}
protected void setViews(View contentView, View controlsView) {
mContentView = contentView;
mControlsView = controlsView;
}
}

View File

@@ -13,6 +13,7 @@ import com.youth.banner.adapter.BannerImageAdapter;
import com.youth.banner.holder.BannerImageHolder;
import com.youth.banner.indicator.CircleIndicator;
import cn.ykbox.dashboard.data.BannerBean;
import cn.ykbox.dashboard.databinding.ActivityGalleryBinding;
/**
@@ -37,9 +38,9 @@ public class GalleryActivity extends BaseActivity {
binding = ActivityGalleryBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.banner.setAdapter(new BannerImageAdapter<DataBean>(DataBean.getTestData()) {
binding.banner.setAdapter(new BannerImageAdapter<BannerBean>(BannerBean.getTestData()) {
@Override
public void onBindView(BannerImageHolder holder, DataBean data, int position, int size) {
public void onBindView(BannerImageHolder holder, BannerBean data, int position, int size) {
Log.d("fullshow", "load" + data.imageRes);
Glide.with(holder.itemView)
.load(data.imageRes)

View File

@@ -0,0 +1,33 @@
package cn.ykbox.dashboard;
import android.os.Bundle;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceFragmentCompat;
public class SettingsActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.settings, new SettingsFragment())
.commit();
}
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
public static class SettingsFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.root_preferences, rootKey);
}
}
}

View File

@@ -32,6 +32,8 @@ public class StartActivity extends AppCompatActivity {
Intent myIntent = new Intent(mContext, BuildingDashboardActivity.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(myIntent);
finish();
}
}, 3000);
}

View File

@@ -0,0 +1,36 @@
package cn.ykbox.dashboard.data;
import java.util.ArrayList;
import java.util.List;
import cn.ykbox.dashboard.R;
public class BannerBean {
public Integer imageRes;
public String imageUrl;
public String title;
public int viewType;
public BannerBean(Integer imageRes, String title, int viewType) {
this.imageRes = imageRes;
this.title = title;
this.viewType = viewType;
}
public BannerBean(String imageUrl, String title, int viewType) {
this.imageUrl = imageUrl;
this.title = title;
this.viewType = viewType;
}
public static List<BannerBean> getTestData() {
List<BannerBean> list = new ArrayList<>();
list.add(new BannerBean(R.drawable.image1, "第3代无线智能中控", 1));
list.add(new BannerBean(R.drawable.image2, "智慧班牌", 3));
list.add(new BannerBean(R.drawable.image3, "无线话筒", 3));
list.add(new BannerBean(R.drawable.image4, "可移动式智能讲桌", 1));
list.add(new BannerBean(R.drawable.image5, "TD2+智慧屏集成讲桌", 1));
list.add(new BannerBean(R.drawable.image6, "TD5+智慧屏集成讲台", 3));
return list;
}
}

View File

@@ -10,16 +10,12 @@
<!-- The primary full-screen view. This can be replaced with whatever view
is needed to present your content, e.g. VideoView, SurfaceView,
TextureView, etc. -->
<TextView
android:id="@+id/fullscreen_content"
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:keepScreenOn="true"
android:text="@string/dummy_content"
android:textColor="?attr/fullscreenTextColor"
android:textSize="50sp"
android:textStyle="bold" />
android:keepScreenOn="true"/>
<!-- This FrameLayout insets its children based on system windows using
android:fitsSystemWindows. -->
@@ -36,15 +32,13 @@
android:layout_gravity="bottom|center_horizontal"
android:orientation="horizontal"
tools:ignore="UselessParent">
<Button
android:id="@+id/dummy_button"
android:id="@+id/settings_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/dummy_button" />
android:text="设置" />
</LinearLayout>
</FrameLayout>

View File

@@ -0,0 +1,9 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/settings"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View File

@@ -0,0 +1,12 @@
<resources>
<!-- Reply Preference -->
<string-array name="reply_entries">
<item>Reply</item>
<item>Reply to all</item>
</string-array>
<string-array name="reply_values">
<item>reply</item>
<item>reply_all</item>
</string-array>
</resources>

View File

@@ -3,4 +3,20 @@
<string name="dummy_button">Dummy Button</string>
<string name="dummy_content">DUMMY\nCONTENT</string>
<string name="title_activity_building_dashboard">BuildingDashboardActivity</string>
<string name="title_activity_settings">SettingsActivity</string>
<!-- Preference Titles -->
<string name="messages_header">Messages</string>
<string name="sync_header">Sync</string>
<!-- Messages Preferences -->
<string name="signature_title">Your signature</string>
<string name="reply_title">Default reply action</string>
<!-- Sync Preferences -->
<string name="sync_title">Sync email periodically</string>
<string name="attachment_title">Download incoming attachments</string>
<string name="attachment_summary_on">Automatically download attachments for incoming emails
</string>
<string name="attachment_summary_off">Only download attachments when manually requested</string>
</resources>

View File

@@ -0,0 +1,9 @@
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory app:title="网页">
<EditTextPreference
app:key="k_url"
app:title="网页地址"
app:defaultValue="http://10.1.58.176:8002"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory>
</PreferenceScreen>