From 7fc22a7c6b1e6648c754836c02b0904360f95e62 Mon Sep 17 00:00:00 2001 From: "xiaoyan159@6800H" Date: Mon, 2 Sep 2024 17:20:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9=E6=8B=96=E5=8A=A8?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E4=B8=8D=E5=86=8D=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=AD=90View=E5=A4=A7=E5=B0=8F=EF=BC=8C?= =?UTF-8?q?=E5=8F=AA=E5=9C=A8=E6=89=8B=E6=8C=87=E6=8A=AC=E8=B5=B7=E6=97=B6?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=A4=A7=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 15 + .idea/.gitignore | 3 + .idea/appInsightsSettings.xml | 26 ++ .idea/compiler.xml | 6 + .idea/deploymentTargetSelector.xml | 10 + .idea/gradle.xml | 19 + .idea/kotlinc.xml | 6 + .idea/migrations.xml | 10 + .idea/misc.xml | 10 + .idea/other.xml | 318 ++++++++++++++ .idea/vcs.xml | 6 + automotive/.gitignore | 1 + automotive/build.gradle | 42 ++ automotive/proguard-rules.pro | 21 + .../hmi/autotest/ExampleInstrumentedTest.kt | 24 ++ automotive/src/main/AndroidManifest.xml | 28 ++ .../library/splitlayout/SplitLayout.java | 392 ++++++++++++++++++ .../SplitLayoutActivity.java | 73 ++++ .../src/main/res/drawable-xxhdpi/icon_app.png | Bin 0 -> 1110 bytes .../src/main/res/drawable-xxhdpi/icon_qq.png | Bin 0 -> 2407 bytes .../main/res/drawable-xxhdpi/icon_taobao.png | Bin 0 -> 2988 bytes .../splithandle_vertical.9.png | Bin 0 -> 595 bytes .../res/drawable/ic_launcher_background.xml | 170 ++++++++ .../res/drawable/ic_launcher_foreground.xml | 30 ++ .../src/main/res/drawable/split_drawable.xml | 16 + .../main/res/layout/activity_split_layout.xml | 109 +++++ .../main/res/mipmap-anydpi/ic_launcher.xml | 6 + .../res/mipmap-anydpi/ic_launcher_round.xml | 6 + .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 1404 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 2898 bytes .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 982 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 1772 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 1900 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 3918 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 2884 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 5914 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 3844 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 7778 bytes automotive/src/main/res/values/color.xml | 9 + .../src/main/res/values/splitlayout.xml | 15 + automotive/src/main/res/values/strings.xml | 5 + automotive/src/main/res/values/styles.xml | 22 + automotive/src/main/res/values/themes.xml | 4 + .../java/com/hmi/autotest/ExampleUnitTest.kt | 17 + build.gradle | 5 + gradle.properties | 23 + gradle/libs.versions.toml | 20 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 185 +++++++++ gradlew.bat | 89 ++++ settings.gradle | 23 + 52 files changed, 1770 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/appInsightsSettings.xml create mode 100644 .idea/compiler.xml create mode 100644 .idea/deploymentTargetSelector.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/kotlinc.xml create mode 100644 .idea/migrations.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/other.xml create mode 100644 .idea/vcs.xml create mode 100644 automotive/.gitignore create mode 100644 automotive/build.gradle create mode 100644 automotive/proguard-rules.pro create mode 100644 automotive/src/androidTest/java/com/hmi/autotest/ExampleInstrumentedTest.kt create mode 100644 automotive/src/main/AndroidManifest.xml create mode 100644 automotive/src/main/java/com/mixiaoxiao/library/splitlayout/SplitLayout.java create mode 100644 automotive/src/main/java/com/mixiaoxiao/splitlayoutsample/SplitLayoutActivity.java create mode 100644 automotive/src/main/res/drawable-xxhdpi/icon_app.png create mode 100644 automotive/src/main/res/drawable-xxhdpi/icon_qq.png create mode 100644 automotive/src/main/res/drawable-xxhdpi/icon_taobao.png create mode 100644 automotive/src/main/res/drawable-xxhdpi/splithandle_vertical.9.png create mode 100644 automotive/src/main/res/drawable/ic_launcher_background.xml create mode 100644 automotive/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 automotive/src/main/res/drawable/split_drawable.xml create mode 100644 automotive/src/main/res/layout/activity_split_layout.xml create mode 100644 automotive/src/main/res/mipmap-anydpi/ic_launcher.xml create mode 100644 automotive/src/main/res/mipmap-anydpi/ic_launcher_round.xml create mode 100644 automotive/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 automotive/src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 automotive/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 automotive/src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 automotive/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 automotive/src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 automotive/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 automotive/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 automotive/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 automotive/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp create mode 100644 automotive/src/main/res/values/color.xml create mode 100644 automotive/src/main/res/values/splitlayout.xml create mode 100644 automotive/src/main/res/values/strings.xml create mode 100644 automotive/src/main/res/values/styles.xml create mode 100644 automotive/src/main/res/values/themes.xml create mode 100644 automotive/src/test/java/com/hmi/autotest/ExampleUnitTest.kt create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/libs.versions.toml create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/appInsightsSettings.xml b/.idea/appInsightsSettings.xml new file mode 100644 index 0000000..371f2e2 --- /dev/null +++ b/.idea/appInsightsSettings.xml @@ -0,0 +1,26 @@ + + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b589d56 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..10a0439 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..1e03240 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..fdf8d99 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0ad17cb --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/other.xml b/.idea/other.xml new file mode 100644 index 0000000..94c96f6 --- /dev/null +++ b/.idea/other.xml @@ -0,0 +1,318 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/automotive/.gitignore b/automotive/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/automotive/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/automotive/build.gradle b/automotive/build.gradle new file mode 100644 index 0000000..1135999 --- /dev/null +++ b/automotive/build.gradle @@ -0,0 +1,42 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.jetbrains.kotlin.android) +} + +android { + namespace 'com.hmi.autotest' + compileSdk 34 + + defaultConfig { + applicationId "com.hmi.autotest" + minSdk 28 + targetSdk 34 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } +} + +dependencies { + + implementation libs.androidx.core.ktx + implementation libs.androidx.appcompat + testImplementation libs.junit + androidTestImplementation libs.androidx.junit + androidTestImplementation libs.androidx.espresso.core +} \ No newline at end of file diff --git a/automotive/proguard-rules.pro b/automotive/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/automotive/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/automotive/src/androidTest/java/com/hmi/autotest/ExampleInstrumentedTest.kt b/automotive/src/androidTest/java/com/hmi/autotest/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..c1d458c --- /dev/null +++ b/automotive/src/androidTest/java/com/hmi/autotest/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.hmi.autotest + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.hmi.autotest", appContext.packageName) + } +} \ No newline at end of file diff --git a/automotive/src/main/AndroidManifest.xml b/automotive/src/main/AndroidManifest.xml new file mode 100644 index 0000000..a03b7bb --- /dev/null +++ b/automotive/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/automotive/src/main/java/com/mixiaoxiao/library/splitlayout/SplitLayout.java b/automotive/src/main/java/com/mixiaoxiao/library/splitlayout/SplitLayout.java new file mode 100644 index 0000000..d1bfd13 --- /dev/null +++ b/automotive/src/main/java/com/mixiaoxiao/library/splitlayout/SplitLayout.java @@ -0,0 +1,392 @@ +package com.mixiaoxiao.library.splitlayout; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.StateListDrawable; +import android.util.AttributeSet; +import android.util.Log; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; + +import com.hmi.autotest.R; + +/** + * SplitLayout github/Mixiaoxiao + * + * @author Mixiaoxiao 2016/08/18 + */ +public class SplitLayout extends ViewGroup { + + static final String TAG = "SplitLayout"; + static final boolean DEBUG = true; + public static final int HORIZONTAL = 0; + public static final int VERTICAL = 1; + + private static final float INVAID_SPLITPOSITION = Float.MIN_VALUE; + private static final int DEFAULT_SPLIT_HANDLE_SIZE_DP = 16; + private static final int DEFAULT_CHILD_MIN_SIZE_DP = 32; + private static final int[] PRESSED_STATE_SET = { android.R.attr.state_pressed }; + private static final int[] EMPTY_STATE_SET = {}; + + private int mOrientation; + + private float mSplitFraction; + private float mSplitPosition = INVAID_SPLITPOSITION; + + private Drawable mHandleDrawable; + private int mHandleSize; + private boolean mHandleHapticFeedback; + + private View mChild0, mChild1; + private float mLastMotionX, mLastMotionY; + private int mChildMinSize; + private int mWidth, mHeight; + private boolean mIsDragging = false; + private Bitmap[] cachedBitmapArray = new Bitmap[2]; + private Bitmap cachedBitmap; + private Canvas cachedCanvas; // 使用双缓冲方式绘制拖动中的View变化,提高效率 + private Paint mPaint = new Paint(); + private int dragForgroundColor = Color.argb(0.88f, 1f, 1f, 1f); + + public SplitLayout(Context context) { + this(context, null, 0); + } + + public SplitLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SplitLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SplitLayout, defStyleAttr, 0); + mOrientation = a.getInteger(R.styleable.SplitLayout_splitOrientation, HORIZONTAL); + mChildMinSize = a.getDimensionPixelSize(R.styleable.SplitLayout_splitChildMinSize, + dp2px(DEFAULT_CHILD_MIN_SIZE_DP)); + mSplitFraction = a.getFloat(R.styleable.SplitLayout_splitFraction, 0.5f); + checkSplitFraction(); + mHandleDrawable = a.getDrawable(R.styleable.SplitLayout_splitHandleDrawable); + if (mHandleDrawable == null) { + StateListDrawable stateListDrawable = new StateListDrawable(); + stateListDrawable.addState(new int[] { android.R.attr.state_pressed }, new ColorDrawable(0x990288d1)); + stateListDrawable.addState(new int[] {}, new ColorDrawable(Color.TRANSPARENT)); + stateListDrawable.setEnterFadeDuration(150); + stateListDrawable.setExitFadeDuration(150); + mHandleDrawable = stateListDrawable; + } + mHandleDrawable.setCallback(this); + mHandleSize = Math.round(a.getDimension(R.styleable.SplitLayout_splitHandleSize, 0f)); + if (mHandleSize <= 0) { + mHandleSize = mOrientation == HORIZONTAL ? mHandleDrawable.getIntrinsicWidth() : mHandleDrawable + .getIntrinsicHeight(); + } + if (mHandleSize <= 0) { + mHandleSize = dp2px(DEFAULT_SPLIT_HANDLE_SIZE_DP); + } + mHandleHapticFeedback = a.getBoolean(R.styleable.SplitLayout_splitHandleHapticFeedback, false); + dragForgroundColor = a.getColor(R.styleable.SplitLayout_splitDragForgroundColor, dragForgroundColor); + a.recycle(); + + mPaint.setColor(dragForgroundColor); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // super.onMeasure(widthMeasureSpec, heightMeasureSpec); + checkChildren(); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + if (widthSize > 0 && heightSize > 0) { + mWidth = widthSize; + mHeight = heightSize; + setMeasuredDimension(widthSize, heightSize); + checkSplitPosition(); + final int splitPosition = Math.round(mSplitPosition); + if (mOrientation == VERTICAL) { + mChild0.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(splitPosition - mHandleSize / 2, MeasureSpec.EXACTLY)); + mChild1.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(heightSize - splitPosition - mHandleSize / 2, MeasureSpec.EXACTLY)); + } else { + mChild0.measure(MeasureSpec.makeMeasureSpec(splitPosition - mHandleSize / 2, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY)); + mChild1.measure( + MeasureSpec.makeMeasureSpec(widthSize - splitPosition - mHandleSize / 2, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY)); + } + + // 初始化双缓冲对应的Bitmap和canvas + cachedBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); + cachedCanvas = new Canvas(cachedBitmap); + } else { + throw new IllegalStateException("SplitLayout with or height must not be MeasureSpec.UNSPECIFIED"); + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int w = r - l; + int h = b - t; + final int splitPosition = Math.round(mSplitPosition); + if (mOrientation == VERTICAL) { + mChild0.layout(0, 0, w, splitPosition - mHandleSize / 2); + mChild1.layout(0, splitPosition + mHandleSize / 2, w, h); + } else { + mChild0.layout(0, 0, splitPosition - mHandleSize / 2, h); + mChild1.layout(splitPosition + mHandleSize / 2, 0, w, h); + } + } + + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouchEvent(MotionEvent ev) { + final int action = ev.getAction(); + float x = ev.getX(); + float y = ev.getY(); + switch (action & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: { + if (isUnderSplitHandle(x, y)) { + if (mHandleHapticFeedback) { + performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + } + mHandleDrawable.setState(PRESSED_STATE_SET); + mIsDragging = true; + getParent().requestDisallowInterceptTouchEvent(true); + getBitmapFromChildView(); // 截屏当前两个子View的图片,用于在拖动过程中的 + invalidate(); + } else { + mIsDragging = false; + } + mLastMotionX = x; + mLastMotionY = y; + break; + } + case MotionEvent.ACTION_MOVE: + if (mIsDragging) { + getParent().requestDisallowInterceptTouchEvent(true); + if (mOrientation == VERTICAL) { + float deltaY = y - mLastMotionY; + onlyUpdateSplitPosition(deltaY); +// updateSplitPositionWithDelta(deltaY); + postInvalidate(); // 使用子View的截图重绘界面 + } else { + float deltaX = x - mLastMotionX; + onlyUpdateSplitPosition(deltaX); +// updateSplitPositionWithDelta(deltaX); + postInvalidate(); + } + mLastMotionX = x; + mLastMotionY = y; + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + if (mIsDragging) { + mHandleDrawable.setState(EMPTY_STATE_SET); + if (mOrientation == VERTICAL) { + float deltaY = y - mLastMotionY; + updateSplitPositionWithDelta(deltaY); + } else { + float deltaX = x - mLastMotionX; + updateSplitPositionWithDelta(deltaX); + } + mLastMotionX = x; + mLastMotionY = y; + mIsDragging = false; + } + + break; + } + return mIsDragging; + } + + private boolean isUnderSplitHandle(float x, float y) { + if (mOrientation == VERTICAL) { + return y >= (mSplitPosition - mHandleSize / 2) && y <= (mSplitPosition + mHandleSize / 2); + } else { + return x >= (mSplitPosition - mHandleSize / 2) && x <= (mSplitPosition + mHandleSize / 2); + } + + } + + private void updateSplitPositionWithDelta(float delta) { + mSplitPosition = mSplitPosition + delta; + checkSplitPosition(); + requestLayout(); + } + + private void onlyUpdateSplitPosition(float delta) { + mSplitPosition = mSplitPosition + delta; + checkSplitPosition(); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (mSplitPosition != INVAID_SPLITPOSITION && mHandleDrawable != null) { + final int splitPosition = Math.round(mSplitPosition); + if (mOrientation == VERTICAL) { + mHandleDrawable.setBounds(0, splitPosition - mHandleSize / 2, mWidth, splitPosition + mHandleSize / 2); + } else { + mHandleDrawable.setBounds(splitPosition - mHandleSize / 2, 0, splitPosition + mHandleSize / 2, mHeight); + } + mHandleDrawable.draw(canvas); + } + + Log.d("SplitLayout", "dispatchDraw"); + if (mIsDragging) { // 开始拖动 + // 获取两个子View的截图Bitmap + cachedCanvas.drawColor(getContext().getColor(android.R.color.transparent), PorterDuff.Mode.CLEAR); + if (cachedBitmapArray != null) { + Rect child0Rect = new Rect(); + Rect child1Rect = new Rect(); + if (mOrientation == VERTICAL) { + child0Rect.set(0, 0, getWidth(), (int) (mSplitPosition - mHandleSize / 2)); + child1Rect.set(0, (int) (mSplitPosition + mHandleSize / 2), getWidth(), getHeight()); + } else { + child0Rect.set(0, 0, (int) (mSplitPosition - mHandleSize / 2), getHeight()); + child1Rect.set((int) (mSplitPosition + mHandleSize / 2), 0, getWidth(), getHeight()); + } +// cachedCanvas.drawBitmap(cachedBitmapArray[0], null, child0Rect, null); + cachedCanvas.drawRect(child0Rect, mPaint); + cachedCanvas.drawBitmap(((BitmapDrawable)getContext().getDrawable(R.drawable.icon_app)).getBitmap(), + child0Rect.centerX() - (getContext().getDrawable(R.drawable.icon_app).getBounds().width()/2), + child0Rect.centerY() - (getContext().getDrawable(R.drawable.icon_app).getBounds().height()/2), null); +// cachedCanvas.drawBitmap(cachedBitmapArray[1], null, child1Rect, null); + cachedCanvas.drawRect(child1Rect, mPaint); + cachedCanvas.drawBitmap(((BitmapDrawable)getContext().getDrawable(R.drawable.icon_app)).getBitmap(), + child1Rect.centerX() - (getContext().getDrawable(R.drawable.icon_app).getBounds().width()/2), + child1Rect.centerY() - (getContext().getDrawable(R.drawable.icon_app).getBounds().height()/2), null); + canvas.drawBitmap(cachedBitmap, 0, 0, null); + } + + } + } + + private void checkSplitFraction() { + if (mSplitFraction < 0) { + mSplitFraction = 0; + } else if (mSplitFraction > 1) { + mSplitFraction = 1; + } + } + + private void checkSplitPosition() { + if (mOrientation == VERTICAL) { + if (mSplitPosition == INVAID_SPLITPOSITION) { + mSplitPosition = mHeight * mSplitFraction; + } + final int min = mChildMinSize + mHandleSize / 2; + if (mSplitPosition < min) { + mSplitPosition = min; + } else { + final int max = mHeight - mChildMinSize - mHandleSize / 2; + if (mSplitPosition > max) { + mSplitPosition = max; + } + } + } else { + if (mSplitPosition == INVAID_SPLITPOSITION) { + mSplitPosition = mWidth * mSplitFraction; + } + final int min = mChildMinSize + mHandleSize / 2; + if (mSplitPosition < min) { + mSplitPosition = min; + } else { + final int max = mWidth - mChildMinSize - mHandleSize / 2; + if (mSplitPosition > max) { + mSplitPosition = max; + } + } + } + } + + private void checkChildren() { + if (getChildCount() == 2) { + mChild0 = getChildAt(0); + mChild1 = getChildAt(1); + } else { + throw new IllegalStateException("SplitLayout ChildCount must be 2."); + } + } + + @Override + public void jumpDrawablesToCurrentState() { + super.jumpDrawablesToCurrentState(); + if (mHandleDrawable != null) { + mHandleDrawable.jumpToCurrentState(); + } + + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + updateSplitPositionWithDelta(0); + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mHandleDrawable; + } + + private int dp2px(float dp) { + return (int) (dp * getContext().getResources().getDisplayMetrics().density + 0.5f); + } + + // 获取当前两个子View的Bitmap截图,用于在拖动过程中的实时绘制 + private void getBitmapFromChildView() { + // 先回收已有的缓存图片 + for (Bitmap bitmap: cachedBitmapArray) { + if (bitmap != null) { + bitmap.recycle(); + } + } + if (mChild0!=null) { + cachedBitmapArray[0] = loadBitmapFromViewBySystem(mChild0); + } + if (mChild1!=null) { + cachedBitmapArray[1] = loadBitmapFromViewBySystem(mChild1); + } + } + + /** + *此方法直接截取屏幕指定view区域的内容 + * @param view 需要截取屏幕的图片view + * @return Bitmap + */ + public static Bitmap loadBitmapFromViewBySystem(View view) { + if (view == null) { + return null; + } + view.setDrawingCacheEnabled(true); + view.buildDrawingCache(); + Bitmap bitmap = view.getDrawingCache(); + return bitmap; + } + + // 设置拖动时前景图片的颜色值 + public void setDragForgroundColor(int dragForgroundColor) { + this.dragForgroundColor = dragForgroundColor; + mPaint.setColor(dragForgroundColor); + } + + public int getDragForgroundColor() { + return dragForgroundColor; + } +} diff --git a/automotive/src/main/java/com/mixiaoxiao/splitlayoutsample/SplitLayoutActivity.java b/automotive/src/main/java/com/mixiaoxiao/splitlayoutsample/SplitLayoutActivity.java new file mode 100644 index 0000000..bc616c9 --- /dev/null +++ b/automotive/src/main/java/com/mixiaoxiao/splitlayoutsample/SplitLayoutActivity.java @@ -0,0 +1,73 @@ +package com.mixiaoxiao.splitlayoutsample; + +import android.app.Activity; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.os.Bundle; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.widget.Toast; + +import com.hmi.autotest.R; +import com.mixiaoxiao.library.splitlayout.SplitLayout; + +public class SplitLayoutActivity extends Activity { + + private SplitLayout mVerticalSplitLayout, mHorizontalSplitLayout; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_split_layout); + mVerticalSplitLayout = (SplitLayout) findViewById(R.id.splitlayout_vertical); + mHorizontalSplitLayout = (SplitLayout) findViewById(R.id.splitlayout_horizontal); + + findViewById(R.id.tv_child0).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Toast.makeText(SplitLayoutActivity.this, "CHILD 0", Toast.LENGTH_SHORT).show(); + Log.d("SplitLayoutActivity", "tv_child0 clicked"); + } + }); + + findViewById(R.id.tv_child0).setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + Log.d("SplitLayoutActivity", "tv_child0 onTouch"); + return false; + } + }); + + findViewById(R.id.layout_child0).setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + Log.d("SplitLayoutActivity", "layout_child0 onTouch"); + return false; + } + }); + } + + public void onClickVerticalSample(View v) { + mVerticalSplitLayout.setVisibility(View.VISIBLE); + mHorizontalSplitLayout.setVisibility(View.GONE); + } + + public void onClickHorizontalSample(View v) { + mVerticalSplitLayout.setVisibility(View.GONE); + mHorizontalSplitLayout.setVisibility(View.VISIBLE); + } +// public void onClickChild0(View v){ +// Toast.makeText(this, "CHILD 0", Toast.LENGTH_SHORT).show(); +// } +// public void onClickChild1(View v){ +// Toast.makeText(this, "CHILD 1", Toast.LENGTH_SHORT).show(); +// } + public void onClickRotateScreen(View v) { + if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } else { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + + } + } +} diff --git a/automotive/src/main/res/drawable-xxhdpi/icon_app.png b/automotive/src/main/res/drawable-xxhdpi/icon_app.png new file mode 100644 index 0000000000000000000000000000000000000000..c4f88ac834ac321f88df1dfbbb212fd471dd8fa9 GIT binary patch literal 1110 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSjKx9jP7LeL$-HD>U=i?iaSW-5 zdpq}HVThps%Tpf(VUAW08Lov68YxUMS8H$XxK~i3`)S4Bz2=wBZTZF${`KDFPwz9> z=k>k2_iQ?Y3|}Jy$AO1@GWYfgJ23E-Klt!%E(24+4(9gl?^y&I4$E5Xsa0=aka>6D z;ah7)mInpweEIh|6&TvB3o3s5F)$vG`LX5NuU*%EHE3>fvcDD;e=X|1eoFMOjyuZg z2e#jTcJIvXpYPcY9`EMe_C@fi1JeiNsE_}}W53?HZ2Gj%*O?{##PH{5*kezoFFMI|N$26OhPebzvuSClY)iA!UBz{|dF zK{=Dli!bwJ7zG;GWoP`oaaEa>z!tIjIo0Mf9or0=ePt% zzlLegUvK?lXvY}Ull{_};aWC4=}<2p@FZAkJ+Dh6_u0wyh*Hu>@;_enGNv;K&7IN}*{rKkw#P^Zs) z4`daXR5i0KEp=;EW>&I);1ehm65Tpy4$y%Y_ApnlcQ|-_yvuQ5$J1(E4TkEchWn%$CAQbBXJt)TZ*#0%nc?xY g_gfc0EU9DM;(MU6kbCJvU_rs)>FVdQ&MBb@07}}<{{R30 literal 0 HcmV?d00001 diff --git a/automotive/src/main/res/drawable-xxhdpi/icon_qq.png b/automotive/src/main/res/drawable-xxhdpi/icon_qq.png new file mode 100644 index 0000000000000000000000000000000000000000..3e075b0bd25ba123e1235d7f5e92986290b29c8d GIT binary patch literal 2407 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 Z?0@bdPRz*je<%O|002ovPDHLkV1lYxQkeh% literal 0 HcmV?d00001 diff --git a/automotive/src/main/res/drawable-xxhdpi/icon_taobao.png b/automotive/src/main/res/drawable-xxhdpi/icon_taobao.png new file mode 100644 index 0000000000000000000000000000000000000000..459fe51a21355a55b63662a10ed74447bd66686e GIT binary patch literal 2988 zcmai0`8(8m8~%J}!;Fw^(uNG7V;MBGU<_&;ODILQ3E@SyaZ=6TYfW_Ipi;z8o#uoI z;gDoP$i6R;tdjEp=hv&Yp=ZEKhez>pezV2JLHm7%C_hJD6yDX??_B#y! zZ-g;BSZ{Qxb%!9j{b>r|bnO2M0M6UO%;elPxA{k|p(7-Tro0kHipt@Cmi~6`dlSFZ z$9wt(~4<9`xAh4E4T%C{`HFFpPLmyFbQ5*UvuSmR37TyLr@#+pNw3I*bC z%PRF9QLwJnVrb2~EkAAdd(FF^BNvt~F_w&6EH!JRY?O-uj?{ic+oz)im5 zUvE!#(75q!RKi>4i+)Qsf_&yDuWc}fWdL5>aW35`7n^Q5`i#-kyCPV66!_P(r!r`k zbL5+u-x)C;U^z4Q1=E>gA)ExdUPc&B-%lVPfH};F=`+f*a>vgLO{|1$en+Rw;(K3R zDBeiidA*~#ck&2P@#Q^ua3TBSjwrq;={eM;8>w-3VcJ(EULB}52|_BatP<=b`W7J> zAnmd}mzvx&qs^U zzw%0Ci+Q(w#C|z4(xK+^t<}okQrzvnVCYR6ty3WM)M!%s2WyJ}i1x10tJMlYe!F4) zyF2L~-DTHjUHxa89)fq*TEJ}{_?4#AZZ+jhQ_tla! z=a3_rn}JJ&x{4!b{hkVjx_FY!8$0fm*)=Q&{Md*b$;u>Uv7U5vF5j`p_d0%G1*PUj z7KLX-pZ#6cL=eyz8fHheizCmW?Ln$ncXr|Azs}Lc>Dj*;)Je+8dtLP_ zBe0(8eT0&eW`KH%XV8A4_9X>-`Ma8?*0~py;dQojSoh5&X1tpNhFmpR^SCu^b7a(( zQ!%S`@(vWEKxeg-YG9G}K<{HM*MeDju8;c7MEzcqA!>g~FSS%TXE%nGmU@kd2nm#) z%J|Vs3L0#j^Ylc;7i|xzm=X6@!3`&-fSyimu9OEiCg$K{l_9o=bfXhZTn!>KIPzDX zEFT({jyW62y^&wXzAQ-JM-wXiay+>C_-BpDF@PeA94Tor+vKtqjpvR??<1&pYpNue z0N=jk^!s02;ZyN0Z`bZ3U(x2cE!iWyI0dF|BJc3%(W4M7o9S_otiL7Xs>9!)5W`5` z*v2e}#XQSn+*Cf8o3rG)y>xGD)%;ATYU7 z*TVg-RWVjn5brKkC`P(V=lYw zE)oa*tJ}3^Kf=s$23*6R(UaZmLrTA&^arUqU>3qcWYyvb#$Z^bt@I+ejSdF}c+MPx ze^4lh)z&v{Iw;O&2(ch=DhRfE2qAVF8ge~KxPlv#N;28?ggVgdy z8{M7=AH(gRg)%f?UEA}DE$IfseB%7S&*HZDntr!#lS{FRP&tNNuH;s^I+#QAUPUg7 zc-kCnM<|>dZ{DBu3V_}z32|FAuvve6IlIHUAxr`5gtQ#pfs0QGD8vWNKWRVIqgMY4A>u3f_ zr(!RgatRIgt|nB4=;LG%Y_We;C$TDbwqz|d_CrAiiqaVaRQsf0b!v+^!J%-ar^ZUy zvsJk40E52Xeb@9#;BGK)CL!5S;(ju>xuk{uP5iocg{U~_o=nkQFquCO0V>PVb4rsiph1fSOA9Ax?ufiy%S$ zJ3k?4zXo{%M$nO3b zvSq@e|^QhiL)H5Y-A(6zn+LCxN1zYB@SkbMell)kDkN509HBhBozFj7ufLIPDgI zz(XAFOu1Z-3m8Scgi|tMn|Ay!Pr=m3$xyCHMVUT#nsw@xtI=_%HxJ$~=KpRf2_ht=@55Av$hdX1X&qi-^M zxFKV%7XZicp3XzGx4jt6zYcBGpjlzqHKg_#@=8#$s>w}K-nVYyyx=}B`3L%1kw zF--MRde-aL*GlnzD~G^P%kpb3S?I)Fv#WNXk(g3nz^f|XR373k}rhl*>Ow&Vs5iqW0*Tm9a2JikO7?TE?!a@7!Hoa{RgIBG?kjgxpb*Mdeb?}pA zlGEY`Z<(O@o+m;JM=MAYs*TSA)g7`196+$--rH5gn@W?RHjC+s^Wy|H`#SK9Ke|Npo7 YsMy^rGpJ=P{!aY{7Uni)911Pwzfn4UPyhe` literal 0 HcmV?d00001 diff --git a/automotive/src/main/res/drawable-xxhdpi/splithandle_vertical.9.png b/automotive/src/main/res/drawable-xxhdpi/splithandle_vertical.9.png new file mode 100644 index 0000000000000000000000000000000000000000..b21477a20a0e67c44c33e6fb942967a067480b24 GIT binary patch literal 595 zcmV-Z0<8UsP)t548EbK6DQ2k0C423-Xw!3XFhbaE1$oC<Uz1(ApC`-vK=l-pEw&O(?xB zFO&+-u|!9NH!$5^pM%@p)wtzVA6DOo&`E03>6v+C3j_vb1cyl zp^bV(#il~pZJF{pIL8t_5r+0ljS9|$(iqn#i-@iWLnRwRaZCfxb3|W+p`t^fe4HV! zSHO=5zb~O%>H|vfv0S|jWz6P7Zp}ATh(8g=e7|YC?UFoOnpyw=002ovPDHLkV1j074CVj; literal 0 HcmV?d00001 diff --git a/automotive/src/main/res/drawable/ic_launcher_background.xml b/automotive/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/automotive/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/automotive/src/main/res/drawable/ic_launcher_foreground.xml b/automotive/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/automotive/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/automotive/src/main/res/drawable/split_drawable.xml b/automotive/src/main/res/drawable/split_drawable.xml new file mode 100644 index 0000000..6721d45 --- /dev/null +++ b/automotive/src/main/res/drawable/split_drawable.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/automotive/src/main/res/layout/activity_split_layout.xml b/automotive/src/main/res/layout/activity_split_layout.xml new file mode 100644 index 0000000..b0f3b43 --- /dev/null +++ b/automotive/src/main/res/layout/activity_split_layout.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + +