Merge branch 'appbase' into mymessagemanager

This commit is contained in:
ZhanGSKen 2025-03-29 09:45:00 +08:00
commit fe70a18547
41 changed files with 907 additions and 272 deletions

View File

@ -24,13 +24,13 @@ android {
defaultConfig { defaultConfig {
applicationId "cc.winboll.studio.appbase" applicationId "cc.winboll.studio.appbase"
minSdkVersion 26 minSdkVersion 24
targetSdkVersion 29 targetSdkVersion 29
versionCode 1 versionCode 1
// versionName // versionName
// .winboll/winbollBuildProps.properties stageCount=0 // .winboll/winbollBuildProps.properties stageCount=0
// Gradle编译环境下合起来的 versionName "${versionName}.0" // Gradle编译环境下合起来的 versionName "${versionName}.0"
versionName "15.1" versionName "15.2"
if(true) { if(true) {
versionName = genVersionName("${versionName}") versionName = genVersionName("${versionName}")
} }

View File

@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Wed Mar 26 15:43:21 HKT 2025 #Sat Mar 29 08:43:44 HKT 2025
stageCount=1 stageCount=1
libraryProject=libappbase libraryProject=libappbase
baseVersion=15.1 baseVersion=15.2
publishVersion=15.1.0 publishVersion=15.2.0
buildCount=0 buildCount=0
baseBetaVersion=15.1.1 baseBetaVersion=15.2.1

View File

@ -8,15 +8,15 @@
android:icon="@drawable/ic_launcher" android:icon="@drawable/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/MyAPPBaseTheme" android:theme="@style/MyAPPBaseTheme"
android:resizeableActivity="true"> android:resizeableActivity="true"
android:process=":App">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:exported="true"
android:resizeableActivity="true" android:resizeableActivity="true"
android:launchMode="singleInstance" android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation">
android:taskAffinity="cc.winboll.studio.appbase.task.main"
android:exported="true">
<intent-filter> <intent-filter>
@ -32,7 +32,18 @@
</activity> </activity>
<activity android:name=".GlobalApplication$CrashActivity"/> <activity
android:name=".activities.NewActivity"
android:label="NewActivity"
android:exported="true"
android:resizeableActivity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"/>
<activity android:name=".activities.New2Activity"
android:label="New2Activity"
android:exported="true"
android:resizeableActivity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"/>
<service <service
android:name=".MyTileService" android:name=".MyTileService"
@ -111,9 +122,6 @@
android:name="android.max_aspect" android:name="android.max_aspect"
android:value="4.0"/> android:value="4.0"/>
<activity android:name=".activities.NewActivity"/>
<activity android:name=".activities.New2Activity"/>
</application> </application>

View File

@ -1,12 +1,10 @@
package cc.winboll.studio.appbase; package cc.winboll.studio.appbase;
import android.app.Activity; import android.app.Activity;
import android.app.ActivityOptions;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
@ -16,17 +14,17 @@ import cc.winboll.studio.appbase.activities.NewActivity;
import cc.winboll.studio.appbase.services.MainService; import cc.winboll.studio.appbase.services.MainService;
import cc.winboll.studio.appbase.services.TestDemoBindService; import cc.winboll.studio.appbase.services.TestDemoBindService;
import cc.winboll.studio.appbase.services.TestDemoService; import cc.winboll.studio.appbase.services.TestDemoService;
import cc.winboll.studio.libappbase.CrashHandler;
import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.GlobalCrashActivity;
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.sos.SOS; import cc.winboll.studio.libappbase.sos.SOS;
import cc.winboll.studio.libappbase.utils.ToastUtils; import cc.winboll.studio.libappbase.utils.ToastUtils;
import cc.winboll.studio.libappbase.widgets.StatusWidget; import cc.winboll.studio.libappbase.widgets.StatusWidget;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity; import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.winboll.LogActivity; import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
import cc.winboll.studio.libappbase.winboll.WinBollActivityManager;
import android.support.v7.widget.Toolbar;
public class MainActivity extends AppCompatActivity implements IWinBollActivity { public class MainActivity extends WinBollActivityBase implements IWinBollActivity {
public static final String TAG = "MainActivity"; public static final String TAG = "MainActivity";
@ -65,15 +63,12 @@ public class MainActivity extends AppCompatActivity implements IWinBollActivity
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_main, menu); getMenuInflater().inflate(R.menu.toolbar_main, menu);
getMenuInflater().inflate(R.menu.toolbar_appbase, menu);
return super.onCreateOptionsMenu(menu); return super.onCreateOptionsMenu(menu);
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == cc.winboll.studio.appbase.R.id.item_log) {
onLogActivity();
return true;
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false // 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
@ -92,6 +87,12 @@ public class MainActivity extends AppCompatActivity implements IWinBollActivity
boolean isDebuging = ((CheckBox)view).isChecked(); boolean isDebuging = ((CheckBox)view).isChecked();
GlobalApplication.setIsDebuging(isDebuging); GlobalApplication.setIsDebuging(isDebuging);
} }
public void onPreviewGlobalCrashActivity(View view) {
Intent intent = new Intent(this, GlobalCrashActivity.class);
intent.putExtra(CrashHandler.EXTRA_CRASH_INFO, "Demo log...");
startActivity(intent);
}
public void onStartCenter(View view) { public void onStartCenter(View view) {
MainService.startMainService(this); MainService.startMainService(this);
@ -136,6 +137,8 @@ public class MainActivity extends AppCompatActivity implements IWinBollActivity
startService(intent); startService(intent);
} }
public void onStopTestDemoService(View view) { public void onStopTestDemoService(View view) {
Intent intent = new Intent(this, TestDemoService.class); Intent intent = new Intent(this, TestDemoService.class);
@ -173,26 +176,8 @@ public class MainActivity extends AppCompatActivity implements IWinBollActivity
} }
public void onTestOpenNewActivity(View view) { public void onTestOpenNewActivity(View view) {
WinBollActivityManager.getInstance(this).startWinBollActivity(this, NewActivity.class); GlobalApplication.getWinBollActivityManager().startWinBollActivity(this, NewActivity.class);
} }
public void onLogActivity() {
Intent intent = new Intent(MainActivity.this, LogActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
// Define the bounds.
Rect bounds = new Rect(500, 300, 100, 0);
// Set the bounds as an activity option.
ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchBounds(bounds);
//Intent intent = new Intent(this, LpgActivity.class);
startActivity(intent, options.toBundle());
//WinBollActivityManager.getInstance(this).startWinBollActivity(this, intent, LogActivity.class);
}
} }

View File

@ -0,0 +1,82 @@
package cc.winboll.studio.appbase;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 15:34:16
* @Describe 应用活动窗口基类
*/
import android.app.Activity;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import cc.winboll.studio.appbase.App;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.winboll.WinBollActivityManager;
public class WinBollActivityBase extends AppCompatActivity implements IWinBollActivity {
public static final String TAG = "WinBollActivityBase";
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
WinBollActivityManager getWinBollActivityManager() {
return WinBollActivityManager.getInstance(GlobalApplication.getInstance());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWinBollActivityManager().add(this);
}
@Override
public void onPostCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onPostCreate(savedInstanceState, persistentState);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == cc.winboll.studio.appbase.R.id.item_log) {
GlobalApplication.getWinBollActivityManager().startLogActivity(this);
return true;
} else if(item.getItemId() == cc.winboll.studio.appbase.R.id.item_minimal) {
//moveTaskToBack(true);
exit();
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false
return super.onOptionsItemSelected(item);
}
void exit() {
YesNoAlertDialog.show(this, "Exit " + getString(R.string.app_name), "Close all activity and exit?", new YesNoAlertDialog.OnDialogResultListener(){
@Override
public void onYes() {
App.getWinBollActivityManager().finishAll();
}
@Override
public void onNo() {
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
getWinBollActivityManager().registeRemove(this);
}
}

View File

@ -7,16 +7,20 @@ package cc.winboll.studio.appbase.activities;
*/ */
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import cc.winboll.studio.appbase.R; import cc.winboll.studio.appbase.R;
import cc.winboll.studio.libappbase.LogView; import cc.winboll.studio.appbase.WinBollActivityBase;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity; import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.winboll.WinBollActivityManager;
public class New2Activity extends Activity implements IWinBollActivity { public class New2Activity extends WinBollActivityBase implements IWinBollActivity {
public static final String TAG = "New2Activity"; public static final String TAG = "New2Activity";
Toolbar mToolbar;
//LogView mLogView; //LogView mLogView;
@Override @Override
@ -36,6 +40,9 @@ public class New2Activity extends Activity implements IWinBollActivity {
// mLogView = findViewById(R.id.logview); // mLogView = findViewById(R.id.logview);
// mLogView.start(); // mLogView.start();
mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
} }
@Override @Override
@ -45,14 +52,32 @@ public class New2Activity extends Activity implements IWinBollActivity {
} }
public void onCloseThisActivity(View view) { public void onCloseThisActivity(View view) {
WinBollActivityManager.getInstance(this).finish(this); GlobalApplication.getWinBollActivityManager().finish(this);
} }
public void onCloseAllActivity(View view) { public void onCloseAllActivity(View view) {
WinBollActivityManager.getInstance(this).finishAll(); GlobalApplication.getWinBollActivityManager().finishAll();
} }
public void onNewActivity(View view) { public void onNewActivity(View view) {
WinBollActivityManager.getInstance(this).startWinBollActivity(this, NewActivity.class); GlobalApplication.getWinBollActivityManager().startWinBollActivity(this, NewActivity.class);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_main, menu);
getMenuInflater().inflate(R.menu.toolbar_appbase, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == cc.winboll.studio.appbase.R.id.item_log) {
GlobalApplication.getWinBollActivityManager().startLogActivity(this);
return true;
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false
return super.onOptionsItemSelected(item);
} }
} }

View File

@ -6,16 +6,20 @@ package cc.winboll.studio.appbase.activities;
*/ */
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import cc.winboll.studio.appbase.R; import cc.winboll.studio.appbase.R;
import cc.winboll.studio.libappbase.LogView; import cc.winboll.studio.appbase.WinBollActivityBase;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity; import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.winboll.WinBollActivityManager;
public class NewActivity extends Activity implements IWinBollActivity { public class NewActivity extends WinBollActivityBase implements IWinBollActivity {
public static final String TAG = "NewActivity"; public static final String TAG = "NewActivity";
Toolbar mToolbar;
//LogView mLogView; //LogView mLogView;
@Override @Override
@ -34,6 +38,9 @@ public class NewActivity extends Activity implements IWinBollActivity {
setContentView(R.layout.activity_new); setContentView(R.layout.activity_new);
// mLogView = findViewById(R.id.logview); // mLogView = findViewById(R.id.logview);
// mLogView.start(); // mLogView.start();
mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
} }
@Override @Override
@ -43,14 +50,32 @@ public class NewActivity extends Activity implements IWinBollActivity {
} }
public void onCloseThisActivity(View view) { public void onCloseThisActivity(View view) {
WinBollActivityManager.getInstance(this).finish(this); GlobalApplication.getWinBollActivityManager().finish(this);
} }
public void onCloseAllActivity(View view) { public void onCloseAllActivity(View view) {
WinBollActivityManager.getInstance(this).finishAll(); GlobalApplication.getWinBollActivityManager().finishAll();
} }
public void onNew2Activity(View view) { public void onNew2Activity(View view) {
WinBollActivityManager.getInstance(this).startWinBollActivity(this, New2Activity.class); GlobalApplication.getWinBollActivityManager().startWinBollActivity(this, New2Activity.class);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_main, menu);
getMenuInflater().inflate(R.menu.toolbar_appbase, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == cc.winboll.studio.appbase.R.id.item_log) {
GlobalApplication.getWinBollActivityManager().startLogActivity(this);
return true;
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false
return super.onOptionsItemSelected(item);
} }
} }

View File

@ -39,28 +39,41 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Android版本10的代号是“Q”API级别是29。 Android 10开始谷歌不再公开使用甜品作为版本代号但内部仍保留了大量与“Q”相关的元素。Android 10本身并没有严格对应某个特定的Java版本但在开发Android 10应用时通常可以使用Java 8或更高版本。 Java 8为Android开发带来了诸如Lambda表达式、方法引用等新特性能提高开发效率和代码可读性与Android 10开发适配良好。Java 9及更高版本也可用于Android 10开发能使用一些新的语言特性和API但可能需要注意兼容性和配置问题。"/> android:text="Android版本10的代号是“Q”API级别是29。 Android 10开始谷歌不再公开使用甜品作为版本代号但内部仍保留了大量与“Q”相关的元素。Android 10本身并没有严格对应某个特定的Java版本但在开发Android 10应用时通常可以使用Java 8或更高版本。 Java 8为Android开发带来了诸如Lambda表达式、方法引用等新特性能提高开发效率和代码可读性与Android 10开发适配良好。Java 9及更高版本也可用于Android 10开发能使用一些新的语言特性和API但可能需要注意兼容性和配置问题。"/>
<LinearLayout <HorizontalScrollView
android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:gravity="right|center_vertical">
<CheckBox <LinearLayout
android:layout_width="wrap_content" android:orientation="horizontal"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Debug Mode" android:gravity="right|center_vertical"
android:layout_weight="1.0" android:layout_width="wrap_content">
android:onClick="onSwitchDebugMode"
android:id="@+id/activitymainCheckBox1"/>
<Button <CheckBox
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Test Application CrashReport" android:text="Debug Mode"
android:textAllCaps="false" android:layout_weight="1.0"
android:onClick="onTestApplicationCrashReport"/> android:onClick="onSwitchDebugMode"
android:id="@+id/activitymainCheckBox1"/>
</LinearLayout> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Application CrashReport"
android:textAllCaps="false"
android:onClick="onTestApplicationCrashReport"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PreviewGlobalCrashActivity"
android:textAllCaps="false"
android:onClick="onPreviewGlobalCrashActivity"/>
</LinearLayout>
</HorizontalScrollView>
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -72,26 +85,27 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="right"> android:gravity="right">
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<Button <Button
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="StartCenter" android:text="StartCenter"
android:textAllCaps="false" android:textAllCaps="false"
android:onClick="onStartCenter"/> android:onClick="onStartCenter"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StopCenter"
android:textAllCaps="false"
android:onClick="onStopCenter"/>
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StopCenter"
android:textAllCaps="false"
android:onClick="onStopCenter"/>
</LinearLayout>
<HorizontalScrollView <HorizontalScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -160,7 +174,6 @@
</HorizontalScrollView> </HorizontalScrollView>
<Button <Button
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -181,14 +194,14 @@
android:text="TestDemoServiceSOS" android:text="TestDemoServiceSOS"
android:textAllCaps="false" android:textAllCaps="false"
android:onClick="onTestDemoServiceSOS"/> android:onClick="onTestDemoServiceSOS"/>
<Button <Button
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="TestOpenNewActivity" android:text="TestOpenNewActivity"
android:textAllCaps="false" android:textAllCaps="false"
android:onClick="onTestOpenNewActivity"/> android:onClick="onTestOpenNewActivity"/>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
@ -198,6 +211,6 @@
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
</LinearLayout> </LinearLayout>

View File

@ -6,11 +6,11 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<android.widget.Toolbar <android.support.v7.widget.Toolbar
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/toolbar"/> android:id="@+id/toolbar"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -6,9 +6,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<android.widget.Toolbar <android.support.v7.widget.Toolbar
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/toolbar"/> android:id="@+id/toolbar"/>
<TextView <TextView
@ -30,13 +30,6 @@
android:textAllCaps="false" android:textAllCaps="false"
android:onClick="onCloseAllActivity"/> android:onClick="onCloseAllActivity"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CloseAllActivity"
android:textAllCaps="false"
android:onClick="onCloseAllActivity"/>
<Button <Button
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -2,8 +2,5 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/item_log"
android:title="Log"/>
</menu> </menu>

View File

@ -9,7 +9,7 @@ android {
buildToolsVersion "32.0.0" buildToolsVersion "32.0.0"
defaultConfig { defaultConfig {
minSdkVersion 26 minSdkVersion 24
targetSdkVersion 29 targetSdkVersion 29
} }
buildTypes { buildTypes {
@ -24,9 +24,13 @@ dependencies {
api fileTree(dir: 'libs', include: ['*.jar']) api fileTree(dir: 'libs', include: ['*.jar'])
// Android // Android
api 'com.android.support:appcompat-v7:28.0.0' // AppCompatActivity //api 'com.android.support:appcompat-v7:28.0.0'
api('com.android.support:appcompat-v7:28.0.0'){
//exclude group: "com.android.support", module: "support-vector-drawable"
exclude group: "com.android.support:animated-vector-drawable:28.0.0"
}
// https://mvnrepository.com/artifact/com.android.support/support-compat // https://mvnrepository.com/artifact/com.android.support/support-compat
api 'com.android.support:support-compat:28.0.0' // //api 'com.android.support:support-compat:28.0.0' //
// https://mvnrepository.com/artifact/com.android.support/support-v4 // https://mvnrepository.com/artifact/com.android.support/support-v4
api 'com.android.support:support-v4:28.0.0' api 'com.android.support:support-v4:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-media-compat // https://mvnrepository.com/artifact/com.android.support/support-media-compat

View File

@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Wed Mar 26 15:43:05 HKT 2025 #Sat Mar 29 08:43:25 HKT 2025
stageCount=1 stageCount=1
libraryProject=libappbase libraryProject=libappbase
baseVersion=15.1 baseVersion=15.2
publishVersion=15.1.0 publishVersion=15.2.0
buildCount=0 buildCount=0
baseBetaVersion=15.1.1 baseBetaVersion=15.2.1

View File

@ -9,28 +9,34 @@
<!-- 发送持久广播 --> <!-- 发送持久广播 -->
<uses-permission android:name="android.permission.BROADCAST_STICKY"/> <uses-permission android:name="android.permission.BROADCAST_STICKY"/>
<!-- 对正在运行的应用重新排序 -->
<uses-permission android:name="android.permission.REORDER_TASKS"/>
<application> <application>
<activity <activity
android:name=".CrashHandler$CrashActivity" android:name=".CrashHandler$CrashActivity"
android:label="CrashActivity" android:label="CrashActivity"
android:launchMode="standard"/> android:launchMode="singleInstance"
android:process=":CrashActivity"/>
<activity <activity
android:name=".GlobalCrashActivity" android:name=".GlobalCrashActivity"
android:label="GlobalCrashActivity" android:label="GlobalCrashActivity"
android:launchMode="standard"/> android:launchMode="singleInstance"
android:process=":GlobalCrashActivity"/>
<activity <activity
android:theme="@android:style/Theme.Holo.Light.NoActionBar" android:name=".winboll.LogActivity"
android:name="cc.winboll.studio.libappbase.winboll.LogActivity" android:label="LogActivity"
android:resizeableActivity="true" android:resizeableActivity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:exported="true"
android:launchMode="singleInstance" android:launchMode="singleInstance"
android:taskAffinity="cc.winboll.studio.libappbase.task.log" android:process=":LogActivity">
android:exported="true">
</activity>
</activity>
<service <service
android:name=".SimpleOperateSignalCenterService" android:name=".SimpleOperateSignalCenterService"
android:exported="true"> android:exported="true">
@ -41,7 +47,8 @@
android:name=".services.TestService" android:name=".services.TestService"
android:exported="true"/> android:exported="true"/>
<receiver android:name=".receiver.MyBroadcastReceiver" <receiver
android:name=".receiver.MyBroadcastReceiver"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
@ -84,7 +91,8 @@
<service android:name="cc.winboll.studio.libappbase.sos.SOSCenter"/> <service android:name="cc.winboll.studio.libappbase.sos.SOSCenter"/>
<receiver android:name="cc.winboll.studio.libappbase.sos.SOSCenterServiceReceiver" <receiver
android:name="cc.winboll.studio.libappbase.sos.SOSCenterServiceReceiver"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>

View File

@ -339,6 +339,7 @@ public final class CrashHandler {
int padding = dp2px(16); int padding = dp2px(16);
message.setPadding(padding, padding, padding, padding); message.setPadding(padding, padding, padding, padding);
message.setText(mLog); message.setText(mLog);
message.setTextColor(Color.BLACK);
message.setTextIsSelectable(true); message.setTextIsSelectable(true);
} }
hw.addView(message); hw.addView(message);

View File

@ -19,32 +19,22 @@ public class GlobalApplication extends Application {
public static final String TAG = "GlobalApplication"; public static final String TAG = "GlobalApplication";
final static String PREFS = GlobalApplication.class.getName() + "PREFS";
final static String PREFS_ISDEBUGING = "PREFS_ISDEBUGING";
private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
volatile static GlobalApplication _GlobalApplication; volatile static GlobalApplication _GlobalApplication;
// 是否处于调试状态 // 是否处于调试状态
volatile static boolean isDebuging = false; volatile static boolean isDebuging = false;
WinBollActivityManager mWinBollActivityManager;
MyActivityLifecycleCallbacks mMyActivityLifecycleCallbacks; MyActivityLifecycleCallbacks mMyActivityLifecycleCallbacks;
public static void setIsDebuging(boolean isDebuging) { public static void setIsDebuging(boolean isDebuging) {
if (_GlobalApplication != null) { if (_GlobalApplication != null) {
GlobalApplication.isDebuging = isDebuging; GlobalApplication.isDebuging = isDebuging;
APPBaseModel.saveBeanToFile(getAPPBaseModelFilePath(), new APPBaseModel(isDebuging)); APPBaseModel.saveBeanToFile(getAPPBaseModelFilePath(), new APPBaseModel(isDebuging));
// 获取SharedPreferences实例
// SharedPreferences sharedPreferences = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
// // 获取编辑器
// SharedPreferences.Editor editor = sharedPreferences.edit();
// // 保存数据
// editor.putBoolean(PREFS_ISDEBUGING, GlobalApplication.isDebuging);
// // 提交更改
// editor.apply();
} }
} }
public static GlobalApplication getInstance() {
return _GlobalApplication;
}
static String getAPPBaseModelFilePath() { static String getAPPBaseModelFilePath() {
return _GlobalApplication.getDataDir().getPath() + "/APPBaseModel.json"; return _GlobalApplication.getDataDir().getPath() + "/APPBaseModel.json";
} }
@ -53,45 +43,40 @@ public class GlobalApplication extends Application {
return isDebuging; return isDebuging;
} }
@Override public static WinBollActivityManager getWinBollActivityManager() {
public Context getApplicationContext() { return WinBollActivityManager.getInstance(_GlobalApplication);
return super.getApplicationContext();
}
public Application getApplication() {
return this;
} }
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
// 保存初始实例
_GlobalApplication = this; _GlobalApplication = this;
setIsDebuging(true);
// 添加日志模块
LogUtils.init(this);
//LogUtils.setLogLevel(LogUtils.LOG_LEVEL.Debug);
//LogUtils.setTAGListEnable(GlobalApplication.TAG, true);
//LogUtils.setALlTAGListEnable(true);
//LogUtils.d(TAG, "LogUtils init");
// 设置应用异常处理窗口
CrashHandler.init(this);
// 初始化 Toast 框架
ToastUtils.init(this);
// 设置应用调试标志 // 应用保存的调试标志
APPBaseModel appBaseModel = APPBaseModel.loadBeanFromFile(getAPPBaseModelFilePath(), APPBaseModel.class); APPBaseModel appBaseModel = APPBaseModel.loadBeanFromFile(getAPPBaseModelFilePath(), APPBaseModel.class);
if (appBaseModel == null) { if (appBaseModel == null) {
setIsDebuging(false); setIsDebuging(false);
} else { } else {
setIsDebuging(appBaseModel.isDebuging()); setIsDebuging(appBaseModel.isDebuging());
} }
LogUtils.init(this); getWinBollActivityManager().setWinBollUI_TYPE(WinBollActivityManager.WinBollUI_TYPE.Service);
//LogUtils.setLogLevel(LogUtils.LOG_LEVEL.Debug); // 注册窗口回调监听
//LogUtils.setTAGListEnable(GlobalApplication.TAG, true); mMyActivityLifecycleCallbacks = new MyActivityLifecycleCallbacks();
//LogUtils.setALlTAGListEnable(true); registerActivityLifecycleCallbacks(mMyActivityLifecycleCallbacks);
//LogUtils.d(TAG, "LogUtils init");
// 设置应用异常处理窗口
CrashHandler.init(this);
// 初始化 Toast 框架
ToastUtils.init(this);
// mWinBollActivityManager = WinBollActivityManager.getInstance(this);
// mWinBollActivityManager.setWinBollUI_TYPE(WinBollActivityManager.WinBollUI_TYPE.Service);
// // 注册回调
// mMyActivityLifecycleCallbacks = new MyActivityLifecycleCallbacks(mWinBollActivityManager);
// registerActivityLifecycleCallbacks(mMyActivityLifecycleCallbacks);
} }

View File

@ -4,26 +4,20 @@ package cc.winboll.studio.libappbase;
* @Author ZhanGSKen@AliYun.Com * @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/11 00:14:05 * @Date 2025/02/11 00:14:05
*/ */
import android.app.Activity;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.SpannableString; import android.support.v7.app.AppCompatActivity;
import android.text.style.ForegroundColorSpan;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import cc.winboll.studio.libappbase.R; import cc.winboll.studio.libappbase.R;
public final class GlobalCrashActivity extends Activity implements MenuItem.OnMenuItemClickListener { public final class GlobalCrashActivity extends AppCompatActivity implements MenuItem.OnMenuItemClickListener {
private static final int MENUITEM_COPY = 0; private static final int MENUITEM_COPY = 0;
private static final int MENUITEM_RESTART = 1; private static final int MENUITEM_RESTART = 1;
@ -45,10 +39,10 @@ public final class GlobalCrashActivity extends Activity implements MenuItem.OnMe
setContentView(R.layout.activity_globalcrash); setContentView(R.layout.activity_globalcrash);
mGlobalCrashReportView = findViewById(R.id.activityglobalcrashGlobalCrashReportView1); mGlobalCrashReportView = findViewById(R.id.activityglobalcrashGlobalCrashReportView1);
mGlobalCrashReportView.setReport(mLog); mGlobalCrashReportView.setReport(mLog);
setActionBar(mGlobalCrashReportView.getToolbar()); setSupportActionBar(mGlobalCrashReportView.getToolbar());
getActionBar().setTitle(CrashHandler.TITTLE); getSupportActionBar().setTitle(CrashHandler.TITTLE);
getActionBar().setSubtitle(GlobalApplication.getAppName(getApplicationContext())); getSupportActionBar().setSubtitle(GlobalApplication.getAppName(getApplicationContext()));
} }
@Override @Override
@ -98,20 +92,4 @@ public final class GlobalCrashActivity extends Activity implements MenuItem.OnMe
mGlobalCrashReportView.updateMenuStyle(); mGlobalCrashReportView.updateMenuStyle();
return true; return true;
} }
void joinQQGroup(String key) {
// 创建Intent
Intent intent = new Intent();
// 设置动作
intent.setAction("android.intent.action.VIEW");
// 设置数据为网址的URI
Uri content_url = Uri.parse("https://www.winboll.cc");
intent.setData(content_url);
// 添加标志
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 设置类名和活动名
intent.setClassName("com.android.browser", "com.android.browser.BrowserActivity");
// 启动Activity
startActivity(intent);
}
} }

View File

@ -8,6 +8,7 @@ package cc.winboll.studio.libappbase;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Color; import android.graphics.Color;
import android.support.v7.widget.Toolbar;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet; import android.util.AttributeSet;
@ -16,7 +17,6 @@ import android.view.MenuItem;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import cc.winboll.studio.libappbase.R; import cc.winboll.studio.libappbase.R;
import android.widget.Toolbar;
public class GlobalCrashReportView extends LinearLayout { public class GlobalCrashReportView extends LinearLayout {

View File

@ -10,6 +10,8 @@ import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -18,6 +20,8 @@ import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.HorizontalScrollView;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.ScrollView; import android.widget.ScrollView;
import android.widget.Spinner; import android.widget.Spinner;
@ -42,6 +46,7 @@ public class LogView extends RelativeLayout {
Context mContext; Context mContext;
ScrollView mScrollView; ScrollView mScrollView;
TextView mTextView; TextView mTextView;
EditText metTagSearch;
CheckBox mSelectableCheckBox; CheckBox mSelectableCheckBox;
CheckBox mSelectAllTAGCheckBox; CheckBox mSelectAllTAGCheckBox;
TAGListAdapter mTAGListAdapter; TAGListAdapter mTAGListAdapter;
@ -107,9 +112,41 @@ public class LogView extends RelativeLayout {
// //
mScrollView = findViewById(cc.winboll.studio.libappbase.R.id.viewlogScrollViewLog); mScrollView = findViewById(cc.winboll.studio.libappbase.R.id.viewlogScrollViewLog);
mTextView = findViewById(cc.winboll.studio.libappbase.R.id.viewlogTextViewLog); mTextView = findViewById(cc.winboll.studio.libappbase.R.id.viewlogTextViewLog);
metTagSearch = findViewById(cc.winboll.studio.libappbase.R.id.tagsearch_et);
// 获取Log Level spinner实例 // 获取Log Level spinner实例
mLogLevelSpinner = findViewById(cc.winboll.studio.libappbase.R.id.viewlogSpinner1); mLogLevelSpinner = findViewById(cc.winboll.studio.libappbase.R.id.viewlogSpinner1);
metTagSearch.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
}
@Override
public void beforeTextChanged(CharSequence charSequence, int p, int p1, int p2) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
LogUtils.d(TAG, s.toString());
if (s.length() > 0) {
scrollToTag(s.toString());
} else {
HorizontalScrollView hsRoot = findViewById(R.id.viewlogHorizontalScrollView1);
hsRoot.smoothScrollTo(0, 0);
mListViewTags.resetScrollToStart();
}
// mListViewTags.postDelayed(new Runnable() {
// @Override
// public void run() {
// mListViewTags.scrollToItem(5);
// }
// }, 100);
}
// 其他方法留空或按需实现
});
(findViewById(cc.winboll.studio.libappbase.R.id.viewlogButtonClean)).setOnClickListener(new View.OnClickListener(){ (findViewById(cc.winboll.studio.libappbase.R.id.viewlogButtonClean)).setOnClickListener(new View.OnClickListener(){
@Override @Override
@ -233,6 +270,60 @@ public class LogView extends RelativeLayout {
scrollLogUp(); scrollLogUp();
} }
public void scrollToTag(final String prefix) {
if (mTAGListAdapter == null || prefix == null || prefix.length() == 0) {
LogUtils.d(TAG, "参数为空,无法滚动");
return;
}
final List<TAGItemModel> itemList = mTAGListAdapter.getItemList();
mListViewTags.post(new Runnable() {
@Override
public void run() {
// 查找匹配的标签位置
int targetPosition = -1;
for (int i = 0; i < itemList.size(); i++) {
String tag = itemList.get(i).getTag();
if (tag != null && tag.toLowerCase().startsWith(prefix.toLowerCase())) {
targetPosition = i;
break;
}
}
if (targetPosition != -1) {
// 优化滚动逻辑
//mListViewTags.setSelection(targetPosition);
//mListViewTags.invalidateViews(); // 强制刷新所有可见项
// 单独刷新目标视图
// View targetView = mListViewTags.getChildAt(targetPosition);
// if (targetView != null) {
// targetView.requestLayout();
// targetView.requestFocus();
// }
final int scrollPosition = targetPosition;
// 延迟滚动确保布局完成
mListViewTags.postDelayed(new Runnable() {
@Override
public void run() {
LogUtils.d(TAG, String.format("scrollPosition %d", scrollPosition));
mListViewTags.scrollToItem(scrollPosition);
}
}, 100);
} else {
LogUtils.d(TAG, "未找到匹配的标签前缀:" + prefix);
}
}
});
}
class LogViewHandler extends Handler { class LogViewHandler extends Handler {
final static int MSG_LOGVIEW_UPDATE = 0; final static int MSG_LOGVIEW_UPDATE = 0;
@ -300,6 +391,30 @@ public class LogView extends RelativeLayout {
public void setChecked(boolean checked) { public void setChecked(boolean checked) {
isChecked = checked; isChecked = checked;
} }
// getter/setter...
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TAGItemModel that = (TAGItemModel) o;
// 手动处理空值比较Java 6 不支持 Objects.equals
if (tag == null) {
return that.tag == null;
} else {
return tag.equals(that.tag);
}
}
@Override
public int hashCode() {
return tag == null ? 0 : tag.hashCode(); // 手动处理空值
}
} }
@ -314,7 +429,11 @@ public class LogView extends RelativeLayout {
mapOrigin = map; mapOrigin = map;
loadMap(mapOrigin); loadMap(mapOrigin);
} }
public List<TAGItemModel> getItemList() {
return itemList;
}
@Override @Override
public int getCount() { public int getCount() {
return itemList.size(); return itemList.size();
@ -344,7 +463,7 @@ public class LogView extends RelativeLayout {
loadMap(mapOrigin); loadMap(mapOrigin);
super.notifyDataSetChanged(); super.notifyDataSetChanged();
} }
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder; ViewHolder holder;

View File

@ -0,0 +1,60 @@
package cc.winboll.studio.libappbase.dialogs;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 17:40:47
* @Date 2024/08/12 14:46:25
* @Describe 询问用户确定与否的选择框
*/
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
public class YesNoAlertDialog {
public static final String TAG = "YesNoAlertDialog";
public static void show(Context context, String szTitle, String szMessage, final OnDialogResultListener listener) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
// set title
alertDialogBuilder.setTitle(szTitle);
// set dialog message
alertDialogBuilder
.setMessage(szMessage)
.setCancelable(true)
.setOnCancelListener(new DialogInterface.OnCancelListener(){
@Override
public void onCancel(DialogInterface dialog) {
listener.onNo();
}
})
.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, close
// current activity
listener.onYes();
}
})
.setNegativeButton("NO", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
public interface OnDialogResultListener {
abstract void onYes();
abstract void onNo();
}
}

View File

@ -9,23 +9,34 @@ import android.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.ListView; import android.widget.ListView;
import android.widget.Scroller;
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogUtils;
public class HorizontalListView extends ListView { public class HorizontalListView extends ListView {
public static final String TAG = "HorizontalListView"; public static final String TAG = "HorizontalListView";
int verticalOffset = 0; private int verticalOffset = 0;
private Scroller scroller;
private int totalWidth;
public HorizontalListView(Context context) { public HorizontalListView(Context context) {
super(context); super(context);
init();
} }
public HorizontalListView(Context context, AttributeSet attrs) { public HorizontalListView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
init();
} }
public HorizontalListView(Context context, AttributeSet attrs, int defStyle) { public HorizontalListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
init();
}
private void init() {
scroller = new Scroller(getContext());
setHorizontalScrollBarEnabled(true);
setVerticalScrollBarEnabled(false);
} }
public void setVerticalOffset(int verticalOffset) { public void setVerticalOffset(int verticalOffset) {
@ -38,28 +49,81 @@ public class HorizontalListView extends ListView {
int childCount = getChildCount(); int childCount = getChildCount();
int left = getPaddingLeft(); int left = getPaddingLeft();
int viewHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); int viewHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
LogUtils.d(TAG, String.format("HorizontalListView的高度 %d", viewHeight)); totalWidth = left;
for (int i = 0; i < childCount; i++) { for (int i = 0; i < childCount; i++) {
View child = getChildAt(i); View child = getChildAt(i);
// 计算每个子视图的宽度和高度
int width = child.getMeasuredWidth(); int width = child.getMeasuredWidth();
int height = child.getMeasuredHeight(); int height = child.getMeasuredHeight();
//LogUtils.d(TAG, String.format("child : width %d , height %d", width, height));
// 设置子视图的位置实现水平布局
child.layout(left, verticalOffset, left + width, verticalOffset + height); child.layout(left, verticalOffset, left + width, verticalOffset + height);
left += width; left += width;
} }
totalWidth = left + getPaddingRight();
} }
@Override @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); int newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
//super.onMeasure(widthMeasureSpec, newHeightMeasureSpec);
int newWidthMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); int newWidthMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
//LogUtils.d(TAG, String.format("newWidthMeasureSpec %d, newHeightMeasureSpec %d", newWidthMeasureSpec, newHeightMeasureSpec));
super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec); super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
} }
@Override
public void computeScroll() {
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
postInvalidate();
}
}
public void smoothScrollTo(int x, int y) {
int dx = x - getScrollX();
int dy = y - getScrollY();
scroller.startScroll(getScrollX(), getScrollY(), dx, dy, 300); // 300ms平滑动画
invalidate();
}
@Override
public int computeHorizontalScrollRange() {
return totalWidth;
}
@Override
public int computeHorizontalScrollOffset() {
return getScrollX();
}
@Override
public int computeHorizontalScrollExtent() {
return getWidth();
}
public void scrollToItem(int position) {
if (position < 0 || position >= getChildCount()) {
LogUtils.d(TAG, "无效的position: " + position);
return;
}
View targetView = getChildAt(position);
int targetLeft = targetView.getLeft();
int scrollX = targetLeft - getPaddingLeft();
// 修正最大滚动范围计算
int maxScrollX = totalWidth;
scrollX = Math.max(0, Math.min(scrollX, maxScrollX));
// 强制重新布局和绘制
requestLayout();
invalidateViews();
smoothScrollTo(scrollX, 0);
LogUtils.d(TAG, String.format("滚动到position: %d, scrollX: %d computeHorizontalScrollRange() %d", position, scrollX, computeHorizontalScrollRange()));
}
public void resetScrollToStart() {
// 强制重新布局和绘制
requestLayout();
invalidateViews();
smoothScrollTo(0, 0);
}
} }

View File

@ -6,7 +6,6 @@ package cc.winboll.studio.libappbase.winboll;
*/ */
import android.app.Activity; import android.app.Activity;
import android.app.Application; import android.app.Application;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogUtils;
@ -15,13 +14,11 @@ import cc.winboll.studio.libappbase.utils.ToastUtils;
public class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks { public class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
public static final String TAG = "MyActivityLifecycleCallbacks"; public static final String TAG = "MyActivityLifecycleCallbacks";
WinBollActivityManager mWinBollActivityManager;
public String mInfo = ""; public String mInfo = "";
public MyActivityLifecycleCallbacks(WinBollActivityManager winBollActivityManager) { public MyActivityLifecycleCallbacks() {
mWinBollActivityManager = winBollActivityManager;
} }
void createActivityeInfo(Activity activity) { void createActivityeInfo(Activity activity) {
@ -50,7 +47,7 @@ public class MyActivityLifecycleCallbacks implements Application.ActivityLifecyc
} }
public void showActivityeInfo() { public void showActivityeInfo() {
ToastUtils.show("ActivityeInfo : " + mInfo); //ToastUtils.show("ActivityeInfo : " + mInfo);
LogUtils.d(TAG, "ActivityeInfo : " + mInfo); LogUtils.d(TAG, "ActivityeInfo : " + mInfo);
} }
@ -60,7 +57,6 @@ public class MyActivityLifecycleCallbacks implements Application.ActivityLifecyc
//System.out.println(activity.getLocalClassName() + " was created"); //System.out.println(activity.getLocalClassName() + " was created");
LogUtils.d(TAG, activity.getLocalClassName() + " was created"); LogUtils.d(TAG, activity.getLocalClassName() + " was created");
createActivityeInfo(activity); createActivityeInfo(activity);
mWinBollActivityManager.add((IWinBollActivity)activity);
} }
@Override @Override
@ -98,6 +94,5 @@ public class MyActivityLifecycleCallbacks implements Application.ActivityLifecyc
public void onActivityDestroyed(Activity activity) { public void onActivityDestroyed(Activity activity) {
//System.out.println(activity.getLocalClassName() + " was destroyed"); //System.out.println(activity.getLocalClassName() + " was destroyed");
LogUtils.d(TAG, activity.getLocalClassName() + " was destroyed"); LogUtils.d(TAG, activity.getLocalClassName() + " was destroyed");
mWinBollActivityManager.registeRemove((IWinBollActivity)activity);
} }
} }

View File

@ -12,7 +12,9 @@ import android.app.ActivityManager;
import android.app.TaskStackBuilder; import android.app.TaskStackBuilder;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -28,27 +30,25 @@ public class WinBollActivityManager {
}; };
// 应用类型标志 // 应用类型标志
volatile static WinBollUI_TYPE _mWinBollUI_TYPE = WinBollUI_TYPE.Service; static volatile WinBollUI_TYPE _mWinBollUI_TYPE = WinBollUI_TYPE.Service;
Context mContext; GlobalApplication mGlobalApplication;
MyActivityLifecycleCallbacks mMyActivityLifecycleCallbacks; static volatile WinBollActivityManager _Instance;
static WinBollActivityManager _mWinBollActivityManager; static volatile Map<String, IWinBollActivity> _mapIWinBollList;
static Map<String, IWinBollActivity> _mapIWinBollList; volatile IWinBollActivity mFirstIWinBollActivity;
IWinBollActivity firstIWinBollActivity;
public WinBollActivityManager(Context context) { WinBollActivityManager(GlobalApplication application) {
mContext = context; mGlobalApplication = application;
LogUtils.d(TAG, "WinBollActivityManager()");
_mapIWinBollList = new HashMap<String, IWinBollActivity>(); _mapIWinBollList = new HashMap<String, IWinBollActivity>();
} }
public static synchronized WinBollActivityManager getInstance(Context context) { public static synchronized WinBollActivityManager getInstance(GlobalApplication application) {
LogUtils.d(TAG, "getInstance"); LogUtils.d(TAG, "getInstance");
if (_mWinBollActivityManager == null) { if (_Instance == null) {
LogUtils.d(TAG, "_mWinBollActivityManager == null"); LogUtils.d(TAG, "_Instance == null");
_mWinBollActivityManager = new WinBollActivityManager(context); _Instance = new WinBollActivityManager(application);
} }
return _mWinBollActivityManager; return _Instance;
} }
// //
@ -69,12 +69,15 @@ public class WinBollActivityManager {
// 把Activity添加到管理中 // 把Activity添加到管理中
// //
public <T extends IWinBollActivity> void add(T iWinBoll) { public <T extends IWinBollActivity> void add(T iWinBoll) {
if (isActive(iWinBoll.getTag())) { String tag = ((IWinBollActivity)iWinBoll).getTag();
LogUtils.d(TAG, String.format("add(...) %s is active.", iWinBoll.getTag())); LogUtils.d(TAG, String.format("add(T iWinBoll) tag is %s", tag));
if (isActive(tag)) {
LogUtils.d(TAG, String.format("isActive(tag) is true, tag : %s.", tag));
} else { } else {
// 设置起始活动窗口以便最后退出时提问 // 设置起始活动窗口以便最后退出时提问
if (firstIWinBollActivity == null && _mapIWinBollList.size() == 0) { if (mFirstIWinBollActivity == null && _mapIWinBollList.size() == 0) {
firstIWinBollActivity = iWinBoll; LogUtils.d(TAG, "Set firstIWinBollActivity, iWinBoll.getTag() is %s" + iWinBoll.getTag());
mFirstIWinBollActivity = iWinBoll;
} }
// 添加到活动窗口列表 // 添加到活动窗口列表
@ -93,11 +96,13 @@ public class WinBollActivityManager {
public <T extends IWinBollActivity> void startWinBollActivity(Context context, Class<T> clazz) { public <T extends IWinBollActivity> void startWinBollActivity(Context context, Class<T> clazz) {
try { try {
// 如果窗口已存在就重启窗口 // 如果窗口已存在就重启窗口
String tag = clazz.newInstance().getTag(); String tag = ((IWinBollActivity)clazz.newInstance()).getTag();
LogUtils.d(TAG, String.format("startWinBollActivity(Context context, Class<T> clazz) tag is %s", tag));
if (isActive(tag)) { if (isActive(tag)) {
resumeActivity(context, tag); resumeActivity(context, tag);
return; return;
} }
//ToastUtils.show("startWinBollActivity(Context context, Class<T> clazz)");
// 新建一个任务窗口 // 新建一个任务窗口
Intent intent = new Intent(context, clazz); Intent intent = new Intent(context, clazz);
@ -106,7 +111,7 @@ public class WinBollActivityManager {
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(EXTRA_TAG, tag); intent.putExtra(EXTRA_TAG, tag);
mContext.startActivity(intent); context.startActivity(intent);
} catch (InstantiationException | IllegalAccessException e) { } catch (InstantiationException | IllegalAccessException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
} }
@ -115,7 +120,8 @@ public class WinBollActivityManager {
public <T extends IWinBollActivity> void startWinBollActivity(Context context, Intent intent, Class<T> clazz) { public <T extends IWinBollActivity> void startWinBollActivity(Context context, Intent intent, Class<T> clazz) {
try { try {
// 如果窗口已存在就重启窗口 // 如果窗口已存在就重启窗口
String tag = clazz.newInstance().getTag(); String tag = ((IWinBollActivity)clazz.newInstance()).getTag();
LogUtils.d(TAG, String.format("startWinBollActivity(Context context, Intent intent, Class<T> clazz) tag is %s", tag));
if (isActive(tag)) { if (isActive(tag)) {
resumeActivity(context, tag); resumeActivity(context, tag);
return; return;
@ -128,24 +134,52 @@ public class WinBollActivityManager {
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(EXTRA_TAG, tag); intent.putExtra(EXTRA_TAG, tag);
mContext.startActivity(intent); context.startActivity(intent);
} catch (InstantiationException | IllegalAccessException e) { } catch (InstantiationException | IllegalAccessException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
} }
} }
public <T extends IWinBollActivity> void startLogActivity(Context context) {
// 如果窗口已存在就重启窗口
String tag = LogActivity.TAG;
if (isActive(tag)) {
resumeActivity(context, tag);
return;
}
// 新建一个任务窗口
Intent intent = new Intent(context, LogActivity.class);
//打开多任务窗口 flags
// Define the bounds.
// Rect bounds = new Rect(0, 0, 800, 200);
// // Set the bounds as an activity option.
// ActivityOptions options = ActivityOptions.makeBasic();
// options.setLaunchBounds(bounds);
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
intent.putExtra(EXTRA_TAG, tag);
//context.startActivity(intent, options.toBundle());
context.startActivity(intent);
}
public boolean isFirstIWinBollActivity(IWinBollActivity iWinBollActivity) { public boolean isFirstIWinBollActivity(IWinBollActivity iWinBollActivity) {
return firstIWinBollActivity != null && firstIWinBollActivity == iWinBollActivity; return mFirstIWinBollActivity != null && mFirstIWinBollActivity == iWinBollActivity;
} }
// //
// 判断 tag绑定的 MyActivity是否存在 // 判断 tag绑定的 MyActivity是否存在
// //
public boolean isActive(String tag) { public boolean isActive(String tag) {
//printAvtivityListInfo(); LogUtils.d(TAG, String.format("isActive(String tag) tag is %s", tag));
//printIWinBollListInfo();
IWinBollActivity iWinBoll = getIWinBoll(tag); IWinBollActivity iWinBoll = getIWinBoll(tag);
if (iWinBoll != null) { if (iWinBoll != null) {
LogUtils.d(TAG, "isActive(...) activity != null tag " + tag); //LogUtils.d(TAG, "isActive(...) activity != null tag " + tag);
//ToastUtils.show("activity != null tag " + tag); //ToastUtils.show("activity != null tag " + tag);
//判断是否为 BaseActivity,如果已经销毁则移除 //判断是否为 BaseActivity,如果已经销毁则移除
if (iWinBoll.getActivity().isFinishing() || iWinBoll.getActivity().isDestroyed()) { if (iWinBoll.getActivity().isFinishing() || iWinBoll.getActivity().isDestroyed()) {
@ -158,12 +192,13 @@ public class WinBollActivityManager {
return true; return true;
} }
} else { } else {
LogUtils.d(TAG, String.format("isActive(...) activity == null\ntag : %s", tag)); LogUtils.d(TAG, String.format("isActive(...) iWinBoll is null tag by %s", tag));
return false; return false;
} }
} }
static IWinBollActivity getIWinBoll(String tag) { static IWinBollActivity getIWinBoll(String tag) {
LogUtils.d(TAG, String.format("getIWinBoll(String tag) %s", tag));
return _mapIWinBollList.get(tag); return _mapIWinBollList.get(tag);
} }
@ -171,8 +206,9 @@ public class WinBollActivityManager {
// 找到tag 绑定的 BaseActivity 通过 getTaskId() 移动到前台 // 找到tag 绑定的 BaseActivity 通过 getTaskId() 移动到前台
// //
public <T extends IWinBollActivity> void resumeActivity(Context context, String tag) { public <T extends IWinBollActivity> void resumeActivity(Context context, String tag) {
LogUtils.d(TAG, "resumeActivty"); LogUtils.d(TAG, "resumeActivity(Context context, String tag)");
T iWinBoll = (T)getIWinBoll(tag); T iWinBoll = (T)getIWinBoll(tag);
LogUtils.d(TAG, String.format("iWinBoll.getTag() %s", iWinBoll.getTag()));
//LogUtils.d(TAG, "activity " + activity.getTag()); //LogUtils.d(TAG, "activity " + activity.getTag());
if (iWinBoll != null && !iWinBoll.getActivity().isFinishing() && !iWinBoll.getActivity().isDestroyed()) { if (iWinBoll != null && !iWinBoll.getActivity().isFinishing() && !iWinBoll.getActivity().isDestroyed()) {
resumeActivity(context, iWinBoll); resumeActivity(context, iWinBoll);
@ -183,16 +219,18 @@ public class WinBollActivityManager {
// 找到tag 绑定的 BaseActivity 通过 getTaskId() 移动到前台 // 找到tag 绑定的 BaseActivity 通过 getTaskId() 移动到前台
// //
public <T extends IWinBollActivity> void resumeActivity(Context context, T iWinBoll) { public <T extends IWinBollActivity> void resumeActivity(Context context, T iWinBoll) {
ActivityManager am = (ActivityManager) iWinBoll.getActivity().getSystemService(Context.ACTIVITY_SERVICE); LogUtils.d(TAG, "resumeActivity(Context context, T iWinBoll)");
ActivityManager am = (ActivityManager) mGlobalApplication.getSystemService(Context.ACTIVITY_SERVICE);
//返回启动它的根任务home 或者 MainActivity //返回启动它的根任务home 或者 MainActivity
Intent intent = new Intent(context, iWinBoll.getClass()); Intent intent = new Intent(mGlobalApplication, iWinBoll.getClass());
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context); TaskStackBuilder stackBuilder = TaskStackBuilder.create(mGlobalApplication);
stackBuilder.addNextIntentWithParentStack(intent); stackBuilder.addNextIntentWithParentStack(intent);
stackBuilder.startActivities(); stackBuilder.startActivities();
//moveTaskToFront(YourTaskId, 0); //moveTaskToFront(YourTaskId, 0);
LogUtils.d(TAG, "am.moveTaskToFront");
//ToastUtils.show("resumeActivity am.moveTaskToFront"); //ToastUtils.show("resumeActivity am.moveTaskToFront");
LogUtils.d(TAG, String.format("iWinBoll.getActivity().getTaskId() %d", iWinBoll.getActivity().getTaskId()));
am.moveTaskToFront(iWinBoll.getActivity().getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION); am.moveTaskToFront(iWinBoll.getActivity().getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION);
LogUtils.d(TAG, "am.moveTaskToFront");
} }
@ -245,11 +283,11 @@ public class WinBollActivityManager {
// 0 1 2 [3] 4 >> 2 // 0 1 2 [3] 4 >> 2
// 0 1 2 3 [4] >> 3 // 0 1 2 3 [4] >> 3
// [0] >> 直接关闭当前窗口 // [0] >> 直接关闭当前窗口
LogUtils.d(TAG, "finish no yet."); //LogUtils.d(TAG, "finish no yet.");
IWinBollActivity preIWinBoll = getPreIWinBoll(iWinBoll); IWinBollActivity preIWinBoll = getPreIWinBoll(iWinBoll);
iWinBoll.getActivity().finish(); iWinBoll.getActivity().finish();
if (preIWinBoll != null) { if (preIWinBoll != null) {
resumeActivity(mContext, preIWinBoll); resumeActivity(mGlobalApplication, preIWinBoll);
} }
} }
@ -268,7 +306,7 @@ public class WinBollActivityManager {
for (Map.Entry<String, IWinBollActivity> entity : _mapIWinBollList.entrySet()) { for (Map.Entry<String, IWinBollActivity> entity : _mapIWinBollList.entrySet()) {
if (entity.getKey().equals(iWinBoll.getTag())) { if (entity.getKey().equals(iWinBoll.getTag())) {
bingo = true; bingo = true;
LogUtils.d(TAG, "bingo"); //LogUtils.d(TAG, "bingo");
break; break;
} }
preIWinBoll = entity.getValue(); preIWinBoll = entity.getValue();

View File

@ -10,8 +10,8 @@
<shape android:shape="rectangle" > <shape android:shape="rectangle" >
<gradient <gradient
android:angle="270" android:angle="270"
android:endColor="@color/colorAccent" android:endColor="#0F000000"
android:startColor="@color/colorAccent" /> android:startColor="#0F000000" />
<corners <corners
android:bottomLeftRadius="6dip" android:bottomLeftRadius="6dip"
android:bottomRightRadius="6dip" android:bottomRightRadius="6dip"

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ff000000"
android:pathData="M4,1C2.89,1 2,1.89 2,3V7C2,8.11 2.89,9 4,9H1V11H13V9H10C11.11,9 12,8.11 12,7V3C12,1.89 11.11,1 10,1H4M4,3H10V7H4V3M3,12V14H5V12H3M14,13C12.89,13 12,13.89 12,15V19C12,20.11 12.89,21 14,21H11V23H23V21H20C21.11,21 22,20.11 22,19V15C22,13.89 21.11,13 20,13H14M3,15V17H5V15H3M14,15H20V19H14V15M3,18V20H5V18H3M6,18V20H8V18H6M9,18V20H11V18H9Z"/>
</vector>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ff000000"
android:pathData="M4,1C2.89,1 2,1.89 2,3V7C2,8.11 2.89,9 4,9H1V11H13V9H10C11.11,9 12,8.11 12,7V3C12,1.89 11.11,1 10,1H4M4,3H10V7H4V3M14,13C12.89,13 12,13.89 12,15V19C12,20.11 12.89,21 14,21H11V23H23V21H20C21.11,21 22,20.11 22,19V15C22,13.89 21.11,13 20,13H14M3.88,13.46L2.46,14.88L4.59,17L2.46,19.12L3.88,20.54L6,18.41L8.12,20.54L9.54,19.12L7.41,17L9.54,14.88L8.12,13.46L6,15.59L3.88,13.46M14,15H20V19H14V15Z"/>
</vector>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ff000000"
android:pathData="M22,6C22,4.9 21.1,4 20,4H4C2.9,4 2,4.9 2,6V18C2,19.1 2.9,20 4,20H20C21.1,20 22,19.1 22,18V6M20,6L12,11L4,6H20M20,18H4V8L12,13L20,8V18Z"/>
</vector>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ff000000"
android:pathData="M24,7H22V13H24V7M24,15H22V17H24V15M20,6C20,4.9 19.1,4 18,4H2C0.9,4 0,4.9 0,6V18C0,19.1 0.9,20 2,20H18C19.1,20 20,19.1 20,18V6M18,6L10,11L2,6H18M18,18H2V8L10,13L18,8V18Z"/>
</vector>

View File

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" <layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:clickable="true" android:clickable="true">
android:layout_width="24dp" <item
android:layout_height="24dp"> android:width="256dp"
<item android:drawable="@drawable/ic_launcher_background"/> android:height="256dp"
<item
android:left="0dp" android:left="0dp"
android:top="0dp" android:top="0dp"
android:right="0dp" android:right="0dp"
android:bottom="0dp" android:bottom="0dp"
android:drawable="@drawable/ic_launcher_foreground"/> android:drawable="@drawable/ic_winboll_logo">
</item>
</layer-list> </layer-list>

View File

@ -5,7 +5,7 @@
android:viewportWidth="108" android:viewportWidth="108"
android:viewportHeight="108"> android:viewportHeight="108">
<path <path
android:fillColor="#FF005C12" android:fillColor="@color/colorPrimary"
android:pathData="M0,0h108v108h-108z" /> android:pathData="M0,0h108v108h-108z" />
<path <path
android:fillColor="#00000000" android:fillColor="#00000000"

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:clickable="true">
<item
android:width="256dp"
android:height="256dp"
android:left="0dp"
android:top="0dp"
android:right="0dp"
android:bottom="0dp"
android:drawable="@drawable/ic_winboll_logo">
</item>
</layer-list>

View File

@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FF1E9B54"
android:strokeColor="#FFF8E733"
android:strokeWidth="20.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M254.63 35.45C374.95 35.45 473.38 133.89 473.38 254.2 473.38 374.51 374.95 472.95 254.63 472.95 134.32 472.95 35.88 374.51 35.88 254.2 35.88 133.89 134.32 35.45 254.63 35.45"/>
<path
android:fillColor="#FF000000"
android:strokeColor="#FF000000"
android:strokeWidth="1.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M257.28 361.25C266.56 361.25 274.14 368.84 274.14 378.11 274.14 387.39 266.56 394.98 257.28 394.98 248.01 394.98 240.42 387.39 240.42 378.11 240.42 368.84 248.01 361.25 257.28 361.25"/>
<path
android:fillColor="#00000000"
android:strokeColor="#FF000000"
android:strokeWidth="30.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M182.16 214.09C181.42 199.71 182.42 177.87 207.64 155.49 213.64 150.16 220.13 146.12 226.28 143.08 238.64 136.97 249.62 134.91 252.55 134.56 252.7 134.54 252.83 134.53 252.94 134.52 253.05 134.51 253.14 134.5 253.2 134.5 255.01 134.48 294.9 136.66 313.05 160.43 332.29 185.63 344.82 221.3 300.07 263.56 263.08 298.49 258.36 318 258.54 317.72"/>
</vector>

View File

@ -0,0 +1,41 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FF1E9B54"
android:strokeColor="#FFF8E733"
android:strokeWidth="20.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M254.63 35.45C374.95 35.45 473.38 133.89 473.38 254.2 473.38 374.51 374.95 472.95 254.63 472.95 134.32 472.95 35.88 374.51 35.88 254.2 35.88 133.89 134.32 35.45 254.63 35.45"/>
<path
android:fillColor="#FFFFFFFF"
android:strokeColor="#FF000000"
android:strokeWidth="20.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M151.49 130.96C151.49 130.96 348.53 130.96 348.53 130.96 348.53 130.96 348.53 393.46 348.53 393.46 348.53 393.46 151.49 393.46 151.49 393.46 151.49 393.46 151.49 130.96 151.49 130.96"/>
<path
android:fillColor="#FFFFFFFF"
android:strokeColor="#FF000000"
android:strokeWidth="20.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M186.28 207.75C186.28 207.75 304.95 207.75 304.95 207.75 304.95 207.75 304.95 205.97 304.95 205.97 304.95 205.97 186.28 205.97 186.28 205.97 186.28 205.97 186.28 207.75 186.28 207.75"/>
<path
android:fillColor="#FFFFFFFF"
android:strokeColor="#FF000000"
android:strokeWidth="20.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M186.28 263.52C186.28 263.52 304.95 263.52 304.95 263.52 304.95 263.52 304.95 264.41 304.95 264.41 304.95 264.41 186.28 264.41 186.28 264.41 186.28 264.41 186.28 263.52 186.28 263.52"/>
<path
android:fillColor="#FFFFFFFF"
android:strokeColor="#FF000000"
android:strokeWidth="20.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M186.28 323.62C186.28 323.62 304.95 323.62 304.95 323.62 304.95 323.62 304.95 320.62 304.95 320.62 304.95 320.62 186.28 320.62 186.28 320.62 186.28 320.62 186.28 323.62 186.28 323.62"/>
</vector>

View File

@ -0,0 +1,48 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FF1E9B54"
android:strokeColor="#FFF8E733"
android:strokeWidth="20.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M254.63 35.45C374.95 35.45 473.38 133.89 473.38 254.2 473.38 374.51 374.95 472.95 254.63 472.95 134.32 472.95 35.88 374.51 35.88 254.2 35.88 133.89 134.32 35.45 254.63 35.45"/>
<path
android:fillColor="#FFFFFFFF"
android:strokeColor="#FFFFFFFF"
android:strokeWidth="1.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M257.28 361.25C266.56 361.25 274.14 368.84 274.14 378.11 274.14 387.39 266.56 394.98 257.28 394.98 248.01 394.98 240.42 387.39 240.42 378.11 240.42 368.84 248.01 361.25 257.28 361.25"/>
<path
android:fillColor="#00000000"
android:strokeColor="#FF000000"
android:strokeWidth="30.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M182.16 214.09C181.42 199.71 182.42 177.87 207.64 155.49 213.64 150.16 220.13 146.12 226.28 143.08 238.64 136.97 249.62 134.91 252.55 134.56 252.7 134.54 252.83 134.53 252.94 134.52 253.05 134.51 253.14 134.5 253.2 134.5 255.01 134.48 294.9 136.66 313.05 160.43 332.29 185.63 344.82 221.3 300.07 263.56 263.08 298.49 258.36 318 258.54 317.72"/>
<path
android:fillColor="#00000000"
android:strokeColor="#FFFFFFFF"
android:strokeWidth="30.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M103.77 307.45C103.02 293.07 104.03 271.24 129.24 248.85 135.25 243.52 141.74 239.48 147.89 236.44 160.24 230.34 171.23 228.28 174.15 227.92 174.31 227.9 174.44 227.89 174.55 227.88 174.66 227.87 174.75 227.86 174.81 227.86 176.62 227.85 216.5 230.02 234.65 253.79 253.9 278.99 266.43 314.66 221.67 356.93 184.69 391.85 179.97 411.36 180.15 411.08"/>
<path
android:fillColor="#00000000"
android:strokeColor="#FFFFFFFF"
android:strokeWidth="30.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M248.17 309.83C247.43 295.45 248.43 273.62 273.64 251.23 279.65 245.9 286.14 241.86 292.29 238.82 304.65 232.72 315.63 230.65 318.55 230.3 318.71 230.28 318.84 230.27 318.95 230.26 319.06 230.25 319.15 230.24 319.21 230.24 321.02 230.22 360.9 232.4 379.06 256.17 398.3 281.37 410.83 317.04 366.08 359.31 329.09 394.23 324.37 413.74 324.55 413.46"/>
<path
android:fillColor="#00000000"
android:strokeColor="#FFFFFFFF"
android:strokeWidth="30.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M182.16 214.09C181.42 199.71 182.42 177.87 207.64 155.49 213.64 150.16 220.13 146.12 226.28 143.08 238.64 136.97 249.62 134.91 252.55 134.56 252.7 134.54 252.83 134.53 252.94 134.52 253.05 134.51 253.14 134.5 253.2 134.5 255.01 134.48 294.9 136.66 313.05 160.43 332.29 185.63 344.82 221.3 300.07 263.56 263.08 298.49 258.36 318 258.54 317.72"/>
</vector>

View File

@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FF1E9B54"
android:strokeColor="#FFF8E733"
android:strokeWidth="20.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M254.63 35.45C374.95 35.45 473.38 133.89 473.38 254.2 473.38 374.51 374.95 472.95 254.63 472.95 134.32 472.95 35.88 374.51 35.88 254.2 35.88 133.89 134.32 35.45 254.63 35.45"/>
<path
android:fillColor="#FFFFFFFF"
android:strokeColor="#FFFFFFFF"
android:strokeWidth="1.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M257.28 361.25C266.56 361.25 274.14 368.84 274.14 378.11 274.14 387.39 266.56 394.98 257.28 394.98 248.01 394.98 240.42 387.39 240.42 378.11 240.42 368.84 248.01 361.25 257.28 361.25"/>
</vector>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:clickable="true">
<item android:drawable="@drawable/ic_launcher_background"/>
<item
android:left="0dp"
android:top="0dp"
android:right="0dp"
android:bottom="0dp"
android:drawable="@drawable/ic_winboll_logo"/>
</layer-list>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="180"
android:endColor="#FFFFFFFF"
android:startColor="#FFFFFFFF"
android:type="linear" />
<corners android:radius="10dp" />
</shape>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#000000" /> <!-- 这里可调整边框宽度和颜色 -->
<solid android:color="@android:color/transparent" />
</shape>

View File

@ -7,9 +7,9 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/viewglobalcrashreportLinearLayout1"> android:id="@+id/viewglobalcrashreportLinearLayout1">
<android.widget.Toolbar <android.support.v7.widget.Toolbar
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/viewglobalcrashreportToolbar1"/> android:id="@+id/viewglobalcrashreportToolbar1"/>
<ScrollView <ScrollView

View File

@ -83,13 +83,21 @@
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"/> android:layout_marginRight="5dp"/>
<EditText
android:layout_width="50dp"
android:ems="10"
android:layout_height="wrap_content"
android:singleLine="true"
android:id="@+id/tagsearch_et"/>
<HorizontalScrollView <HorizontalScrollView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@drawable/bg_border" android:background="@drawable/bg_border"
android:scrollbars="none" android:scrollbars="none"
android:padding="5dp" android:padding="5dp"
android:layout_weight="1.0"> android:layout_weight="1.0"
android:id="@+id/viewlogHorizontalScrollView1">
<cc.winboll.studio.libappbase.views.HorizontalListView <cc.winboll.studio.libappbase.views.HorizontalListView
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/item_minimal"
android:title="MINIMAL"
android:icon="@drawable/ic_winboll_point"
app:showAsAction="always"/>
<item
android:id="@+id/item_about"
android:title="ABOUT"
android:icon="@drawable/ic_winboll_logo"
app:showAsAction="always"/>
<item
android:id="@+id/item_help"
android:title="HELP"
android:icon="@drawable/ic_winboll_help"
app:showAsAction="always"/>
<item
android:id="@+id/item_log"
android:title="LOG"
android:icon="@drawable/ic_winboll_log"
app:showAsAction="always"/>
</menu>