diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/ViewExtras.java b/autojs/src/main/java/com/stardust/autojs/core/ui/ViewExtras.java index d63bc9454..3b66c2847 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/ViewExtras.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/ViewExtras.java @@ -16,8 +16,20 @@ public class ViewExtras { private static final String LOG_TAG = "ViewExtras"; private NativeView mNativeView; - private ViewAttributes mViewAttributes; + /** 创建该 view 的 ViewAttributes 时所用的解析器,按 view 固定下来。 */ + private ResourceParser mResourceParser; + // 只保留弱引用:脚本退出后不应再由 ViewExtras 静态持有 ScriptRuntime 的资源。 + private static volatile java.lang.ref.WeakReference sResourceParser; + + public static void setResourceParser(ResourceParser parser) { + sResourceParser = new java.lang.ref.WeakReference<>(parser); + } + + private static ResourceParser globalParser() { + java.lang.ref.WeakReference ref = sResourceParser; + return ref == null ? null : ref.get(); + } public static ViewExtras get(View view) { ViewExtras extras; @@ -32,6 +44,13 @@ public static ViewExtras get(View view) { return extras; } + public static ViewAttributes getViewAttributes(View view) { + ViewExtras extras = get(view); + // 后启动的脚本会覆盖静态 parser;优先用本 view 创建时绑定的那个, + // 否则旧脚本控件的属性解析会落到另一个脚本的运行时上。 + ResourceParser parser = extras.mResourceParser; + return getViewAttributes(view, parser != null ? parser : globalParser()); + } public static ViewAttributes getViewAttributes(View view, ResourceParser parser) { ViewExtras extras = get(view); @@ -39,11 +58,11 @@ public static ViewAttributes getViewAttributes(View view, ResourceParser parser) if (attributes == null) { attributes = ViewAttributesFactory.create(parser, view); extras.setViewAttributes(attributes); + extras.mResourceParser = parser; } return attributes; } - public static NativeView getNativeView(Scriptable scope, View view, Class staticType, ScriptRuntime runtime) { ViewExtras extras = get(view); NativeView nativeView = extras.getNativeView(); @@ -59,6 +78,30 @@ public static NativeView getNativeView(View view) { return extras.getNativeView(); } + public static void setAttr(View view, String name, Object value) { + ViewAttributes attrs = getViewAttributes(view); + attrs.setAttr(name, String.valueOf(value)); + } + + public static Object getAttr(View view, String name) { + ViewExtras extras = get(view); + ViewAttributes attrs = extras.getViewAttributes(); + if (attrs != null) { + return attrs.getAttrValue(name); + } + return null; + } + + public static NativeView getOrCreateNativeView(Scriptable scope, View view, ScriptRuntime runtime) { + ViewExtras extras = get(view); + NativeView nativeView = extras.getNativeView(); + if (nativeView == null) { + nativeView = new NativeView(scope, view, view.getClass(), runtime); + extras.setNativeView(nativeView); + } + return nativeView; + } + public final NativeView getNativeView() { return mNativeView; } @@ -74,4 +117,4 @@ public final void setNativeView(NativeView nativeView) { public final void setViewAttributes(ViewAttributes viewAttributes) { mViewAttributes = viewAttributes; } -} +} \ No newline at end of file diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/attribute/ViewAttributes.java b/autojs/src/main/java/com/stardust/autojs/core/ui/attribute/ViewAttributes.java index a35796684..589ce387c 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/attribute/ViewAttributes.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/attribute/ViewAttributes.java @@ -165,6 +165,10 @@ public void setAttrValue(String name, String value) { } } + public void setAttr(String name, Object value) { + setAttrValue(name, String.valueOf(value)); + } + @SuppressLint("ClickableViewAccessibility") private void init() { onRegisterAttrs(); diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/AttrSupport.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/AttrSupport.java new file mode 100644 index 000000000..23bd592b9 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/AttrSupport.java @@ -0,0 +1,60 @@ +package com.stardust.autojs.core.ui.widget; + +import android.view.View; +import android.view.ViewGroup; + +import com.stardust.autojs.core.ui.ViewExtras; +import com.stardust.autojs.core.ui.attribute.ViewAttributes; + +import org.mozilla.javascript.ScriptRuntime; +import org.mozilla.javascript.Undefined; + +public interface AttrSupport { + + default void attr(String name, Object value) { + ViewAttributes attrs = ViewExtras.getViewAttributes((View) this); + if (attrs != null) { + attrs.setAttr(name, ScriptRuntime.toString(value)); + } + } + + default Object attr(String name) { + ViewAttributes attrs = ViewExtras.getViewAttributes((View) this); + if (attrs != null) { + return attrs.getAttrValue(name); + } + return Undefined.SCRIPTABLE_UNDEFINED; + } + + default void setWidth(int width) { + if (this instanceof View) { + View view = (View) this; + ViewGroup.LayoutParams params = view.getLayoutParams(); + if (params != null) { + params.width = width; + view.setLayoutParams(params); + view.requestLayout(); + } + } + } + + default void setHeight(int height) { + if (this instanceof View) { + View view = (View) this; + ViewGroup.LayoutParams params = view.getLayoutParams(); + if (params != null) { + params.height = height; + view.setLayoutParams(params); + view.requestLayout(); + } + } + } + + default int getWidth() { + return this instanceof View ? ((View) this).getWidth() : 0; + } + + default int getHeight() { + return this instanceof View ? ((View) this).getHeight() : 0; + } +} \ No newline at end of file diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsButton.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsButton.java index 126eec6d2..48d05ca81 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsButton.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsButton.java @@ -12,7 +12,7 @@ */ @SuppressLint("AppCompatCustomView") -public class JsButton extends Button { +public class JsButton extends Button implements AttrSupport { public JsButton(Context context) { super(context); } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsEditText.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsEditText.java index 9c0506599..d97da64c9 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsEditText.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsEditText.java @@ -12,7 +12,7 @@ */ @SuppressLint("AppCompatCustomView") -public class JsEditText extends EditText { +public class JsEditText extends EditText implements AttrSupport { public JsEditText(Context context) { super(context); } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsFrameLayout.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsFrameLayout.java index 3cad32dbc..129dcd8a0 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsFrameLayout.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsFrameLayout.java @@ -17,7 +17,7 @@ * Created by Stardust on 2017/5/14. */ -public class JsFrameLayout extends FrameLayout { +public class JsFrameLayout extends FrameLayout implements AttrSupport { public JsFrameLayout(@NonNull Context context) { super(context); } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsGridView.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsGridView.java index d4e5ebd46..e4fa0f014 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsGridView.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsGridView.java @@ -11,7 +11,7 @@ * Created by Stardust on 2018/3/30. */ -public class JsGridView extends JsListView { +public class JsGridView extends JsListView implements AttrSupport { public JsGridView(Context context, ScriptRuntime scriptRuntime) { super(context, scriptRuntime); diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsImageView.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsImageView.java index 97b568606..73f55849a 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsImageView.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsImageView.java @@ -14,7 +14,7 @@ * Created by Stardust on 2017/11/30. */ -public class JsImageView extends RoundedImageView { +public class JsImageView extends RoundedImageView implements AttrSupport { private boolean mCircle; private Drawables mDrawables; diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsLinearLayout.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsLinearLayout.java index 1ec5ec792..987e8d2cb 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsLinearLayout.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsLinearLayout.java @@ -14,7 +14,7 @@ * Created by Stardust on 2017/5/14. */ -public class JsLinearLayout extends LinearLayout { +public class JsLinearLayout extends LinearLayout implements AttrSupport { public JsLinearLayout(Context context) { diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsListView.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsListView.java index 0e849373a..7b6c095c1 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsListView.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsListView.java @@ -21,7 +21,7 @@ * Created by Stardust on 2018/3/28. */ -public class JsListView extends RecyclerView { +public class JsListView extends RecyclerView implements AttrSupport { public interface DataSourceAdapter { diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsRelativeLayout.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsRelativeLayout.java index 703c3f6ce..f45aefd32 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsRelativeLayout.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsRelativeLayout.java @@ -13,7 +13,7 @@ * Created by Stardust on 2017/5/14. */ -public class JsRelativeLayout extends RelativeLayout { +public class JsRelativeLayout extends RelativeLayout implements AttrSupport { public JsRelativeLayout(Context context) { super(context); } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsSpinner.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsSpinner.java index ea77c62ae..d51c296f7 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsSpinner.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsSpinner.java @@ -8,10 +8,13 @@ import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; +import android.widget.AbsListView; import android.widget.ArrayAdapter; import android.widget.TextView; -public class JsSpinner extends androidx.appcompat.widget.AppCompatSpinner { +import com.stardust.autojs.core.ui.ViewExtras; + +public class JsSpinner extends androidx.appcompat.widget.AppCompatSpinner implements AttrSupport { private float mTextSize = -1; private int mTextStyle = -1; @@ -21,6 +24,13 @@ public class JsSpinner extends androidx.appcompat.widget.AppCompatSpinner { private int mEntryTextStyle = -1; private int mEntryTextColor = 0; + private int mEntryHeight = -1; + + private int mDropdownTextColorNormal; + private int mDropdownTextColorSelected; + private int mDropdownBgColorNormal; + private int mDropdownBgColorSelected; + public JsSpinner(Context context) { super(context); } @@ -45,7 +55,6 @@ public JsSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode super(context, attrs, defStyleAttr, mode, popupTheme); } - public float getTextSize() { return mTextSize; } @@ -84,7 +93,6 @@ public void setTextSize(float textSize) { } } - public int getTextStyle() { return mTextStyle; } @@ -113,6 +121,59 @@ public void setTextColor(int textColor) { } } + public void setDropDownMaxHeight(int maxHeightPx) { + try { + java.lang.reflect.Method method = androidx.appcompat.widget.AppCompatSpinner.class + .getDeclaredMethod("getInternalPopup"); + method.setAccessible(true); + Object popup = method.invoke(this); + if (popup != null) { + java.lang.reflect.Method setHeight = popup.getClass() + .getMethod("setHeight", int.class); + setHeight.invoke(popup, maxHeightPx); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void setDropDownItemHeight(int heightPx) { + mEntryHeight = heightPx; + } + + public void setDropdownTextColors(int normalColor, int selectedColor) { + mDropdownTextColorNormal = normalColor; + mDropdownTextColorSelected = selectedColor; + } + + public void setDropdownBackgroundColors(int normalColor, int selectedColor) { + mDropdownBgColorNormal = normalColor; + mDropdownBgColorSelected = selectedColor; + } + + public void setDropdownItems(String[] items) { + int defaultHeight = (int) (48 * getContext().getResources().getDisplayMetrics().density); + setDropdownItems(items, defaultHeight, null, null); + } + + public void setDropdownItems(String[] items, Integer itemHeight) { + setDropdownItems(items, itemHeight, null, null); + } + + public void setDropdownItems(String[] items, Integer itemHeight, Integer itemLayout, Integer dropDownLayout) { + if (items == null || items.length == 0) return; + + if (itemHeight != null) { + mEntryHeight = itemHeight; + } + + int layoutRes = itemLayout != null ? itemLayout : android.R.layout.simple_spinner_item; + int dropDownRes = dropDownLayout != null ? dropDownLayout : android.R.layout.simple_spinner_dropdown_item; + + Adapter adapter = new Adapter(getContext(), layoutRes, items); + adapter.setDropDownViewResource(dropDownRes); + setAdapter(adapter); + } public class Adapter extends ArrayAdapter { @@ -147,6 +208,7 @@ public View getDropDownView(int position, @Nullable View convertView, @NonNull V return view; } TextView textView = (TextView) view; + if (mEntryTextColor != 0) { textView.setTextColor(mEntryTextColor); } @@ -156,7 +218,32 @@ public View getDropDownView(int position, @Nullable View convertView, @NonNull V if (mEntryTextStyle != -1) { textView.setTypeface(textView.getTypeface(), mEntryTextStyle); } + + if (position == getSelectedItemPosition()) { + if (mDropdownTextColorSelected != 0) { + textView.setTextColor(mDropdownTextColorSelected); + } + if (mDropdownBgColorSelected != 0) { + textView.setBackgroundColor(mDropdownBgColorSelected); + } + } else { + if (mDropdownTextColorNormal != 0) { + textView.setTextColor(mDropdownTextColorNormal); + } + if (mDropdownBgColorNormal != 0) { + textView.setBackgroundColor(mDropdownBgColorNormal); + } + } + + if (mEntryHeight > 0) { + AbsListView.LayoutParams lp = new AbsListView.LayoutParams( + AbsListView.LayoutParams.MATCH_PARENT, + mEntryHeight + ); + textView.setLayoutParams(lp); + } + return textView; } } -} +} \ No newline at end of file diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsTabLayout.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsTabLayout.java index 88f7aef38..cfd96e971 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsTabLayout.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsTabLayout.java @@ -5,7 +5,7 @@ import com.google.android.material.tabs.TabLayout; -public class JsTabLayout extends TabLayout { +public class JsTabLayout extends TabLayout implements AttrSupport { public JsTabLayout(Context context) { super(context); diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsTextView.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsTextView.java index e91153db6..2d2431ba3 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsTextView.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsTextView.java @@ -12,7 +12,7 @@ */ @SuppressLint("AppCompatCustomView") -public class JsTextView extends TextView { +public class JsTextView extends TextView implements AttrSupport { public JsTextView(Context context) { super(context); diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsToolbar.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsToolbar.java index 95304c6e4..5bd900123 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsToolbar.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsToolbar.java @@ -12,7 +12,7 @@ import com.stardust.autojs.R; -public class JsToolbar extends Toolbar { +public class JsToolbar extends Toolbar implements AttrSupport { public JsToolbar(Context context) { super(context); diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsWebView.kt b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsWebView.kt index fa310a43b..4d171dd27 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsWebView.kt +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsWebView.kt @@ -5,9 +5,12 @@ import android.content.Context import android.util.AttributeSet import android.webkit.WebView import androidx.webkit.WebViewAssetLoader +import com.stardust.autojs.core.ui.ViewExtras import com.stardust.autojs.core.web.JsBridge +import org.mozilla.javascript.ScriptRuntime import java.io.File + @SuppressLint("SetJavaScriptEnabled") open class JsWebView : WebView { //val events = EventEmitter() @@ -55,4 +58,20 @@ open class JsWebView : WebView { fun injectionJsBridge() { JsBridge.injectionJsBridge(this) } + + fun attr(name: String?, value: Any?) { + val attrs = ViewExtras.getViewAttributes(this) + if (attrs != null) { + attrs.setAttr(name, ScriptRuntime.toString(value)) + } + } + + fun attr(name: String?): Any? { + val attrs = ViewExtras.getViewAttributes(this) + if (attrs != null) { + return attrs.getAttrValue(name) + } + return null + } + } diff --git a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.kt b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.kt index a91da9942..3c6ea886c 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.kt +++ b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.kt @@ -21,12 +21,10 @@ import org.mozilla.javascript.Script import org.mozilla.javascript.Scriptable import org.mozilla.javascript.ScriptableObject import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider +import org.mozilla.javascript.lc.type.TypeInfo import java.io.IOException import java.io.InputStreamReader - -/** - * Created by Stardust on 2017/4/2. - */ +import java.net.URI open class RhinoJavaScriptEngine(private val mAndroidContext: android.content.Context) : JavaScriptEngine() { @@ -34,14 +32,14 @@ open class RhinoJavaScriptEngine(private val mAndroidContext: android.content.Co private val wrapFactory = WrapFactory() val context: Context = enterContext() private val mScriptable: TopLevelScope = createScope(this.context) - lateinit var thread: Thread + var thread: Thread? = null private set private val initScript: Script by lazy