add: custom shortcut icon

This commit is contained in:
hyb1996
2017-10-25 16:43:55 +08:00
parent cf82cd2802
commit 98b3fb2c09
20 changed files with 417 additions and 77 deletions

View File

@@ -81,6 +81,10 @@
<activity android:name=".ui.login.LoginActivity_"/>
<activity android:name=".ui.build.BuildActivity_"/>
<activity android:name=".ui.doc.DocumentationActivity_"/>
<activity android:name=".ui.shortcut.ShortcutIconSelectActivity_"/>
<activity
android:name=".ui.shortcut.ShortcutCreateActivity"
android:theme="@style/AppTheme.Transparent"/>
<activity android:name=".external.widget.ScriptWidgetSettingsActivity_">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>

View File

@@ -45,29 +45,19 @@ public class ImportIntentActivity extends BaseActivity {
Uri uri = intent.getData();
if (uri != null && "content".equals(uri.getScheme())) {
String ext = PFiles.getExtension(uri.getScheme());
if(TextUtils.isEmpty(ext)){
if (TextUtils.isEmpty(ext)) {
ext = "js";
}
InputStream stream = getContentResolver().openInputStream(uri);
new ScriptOperations(this, null)
.importFile("", stream, ext)
.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
finish();
}
});
.subscribe(s -> finish());
} else {
final String path = intent.getData().getPath();
if (!TextUtils.isEmpty(path)) {
new ScriptOperations(this, null)
.importFile(path)
.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
finish();
}
});
.subscribe(s -> finish());
}
}
}

View File

@@ -5,6 +5,8 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import com.stardust.scriptdroid.tool.BitmapTool;
/**
* Created by Stardust on 2017/1/20.
*/
@@ -68,7 +70,11 @@ public class Shortcut {
if (mIconRes != null) {
throw new IllegalStateException("Cannot set both iconRes and icon");
}
mIcon = icon;
if (icon.getByteCount() > 1024 * 100) {
mIcon = BitmapTool.scaleBitmap(icon, 100, 100);
}else {
mIcon = icon;
}
return this;
}

View File

@@ -1,7 +1,10 @@
package com.stardust.scriptdroid.tool;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
/**
* Created by Stardust on 2017/4/22.
@@ -22,50 +25,15 @@ public class BitmapTool {
return Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
}
/*
public static MatOfDMatch matchesBitmaps(Bitmap bitmap1, Bitmap bitmap2) {
FeatureDetector detector = FeatureDetector.create(FeatureDetector.BRISK);
DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
Mat descriptors1 = computeDescriptors(bitmap1, detector, descriptor);
Mat descriptors2 = computeDescriptors(bitmap2, detector, descriptor);
MatOfDMatch matches = new MatOfDMatch();
matcher.match(descriptors1, descriptors2, matches);
return matches;
public static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap b = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
drawable.draw(c);
return b;
}
private static Mat computeDescriptors(Bitmap bitmap, FeatureDetector detector, DescriptorExtractor descriptor) {
Mat mat = bitmapToMat(bitmap.copy(bitmap.getConfig(), true));
Mat descriptors = new Mat();
MatOfKeyPoint keyPoints1 = new MatOfKeyPoint();
detector.detect(mat, keyPoints1);
descriptor.compute(mat, keyPoints1, descriptors);
return descriptors;
}
private static Mat bitmapToMat(Bitmap bmp) {
Mat mat = new Mat(bmp.getWidth(), bmp.getHeight(), CvType.CV_8UC1);
Utils.bitmapToMat(bmp, mat);
return mat;
}
public static Core.MinMaxLocResult templateMatching(Bitmap bitmap, Bitmap tmp, int matchMethod) {
Mat img = bitmapToMat(bitmap);
Mat template = bitmapToMat(tmp);
// / Create the result matrix
int result_cols = img.cols() - template.cols() + 1;
int result_rows = img.rows() - template.rows() + 1;
Mat result = new Mat(result_rows, result_cols, CvType.CV_32FC1);
// / Do the Matching and Normalize
Imgproc.matchTemplate(img, template, result, matchMethod);
Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
// / Localizing the best match with minMaxLoc
Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
return mmr;
}
*/
}

View File

@@ -1,6 +1,7 @@
package com.stardust.scriptdroid.ui.common;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.os.Looper;
import android.support.annotation.NonNull;
@@ -27,6 +28,7 @@ import com.stardust.scriptdroid.io.StorageFileProvider;
import com.stardust.scriptdroid.model.sample.Sample;
import com.stardust.scriptdroid.network.download.DownloadManager;
import com.stardust.scriptdroid.ui.filechooser.FileChooserDialogBuilder;
import com.stardust.scriptdroid.ui.shortcut.ShortcutCreateActivity;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import org.reactivestreams.Publisher;
@@ -102,12 +104,7 @@ public class ScriptOperations {
public void newScriptFile() {
showFileNameInputDialog("", "js")
.subscribe(new Consumer<String>() {
@Override
public void accept(@io.reactivex.annotations.NonNull String input) throws Exception {
createScriptFile(getCurrentDirectoryPath() + input + ".js", null, true);
}
});
.subscribe(input -> createScriptFile(getCurrentDirectoryPath() + input + ".js", null, true));
}
public Observable<String> importFile(final String pathFrom) {
@@ -235,8 +232,8 @@ public class ScriptOperations {
}
public void createShortcut(ScriptFile file) {
Scripts.createShortcut(file);
showMessage(R.string.text_already_create);
mContext.startActivity(new Intent(mContext, ShortcutCreateActivity.class)
.putExtra(ShortcutCreateActivity.EXTRA_FILE, file));
}
public void delete(final ScriptFile scriptFile) {

View File

@@ -1,22 +1,16 @@
package com.stardust.scriptdroid.ui.main;
import android.Manifest;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.Menu;
@@ -27,14 +21,12 @@ import com.qq.e.comm.DownloadService;
import com.stardust.app.FragmentPagerAdapterBuilder;
import com.stardust.app.OnActivityResultDelegate;
import com.stardust.enhancedfloaty.FloatyService;
import com.stardust.pio.PFile;
import com.stardust.pio.PFiles;
import com.stardust.scriptdroid.BuildConfig;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.ui.common.NotAskAgainDialog;
import com.stardust.scriptdroid.ui.common.ScriptOperations;
import com.stardust.scriptdroid.ui.doc.OnlineDocsFragment_;
import com.stardust.scriptdroid.ui.floating.FloatyWindowManger;
import com.stardust.scriptdroid.io.StorageFileProvider;
@@ -78,6 +70,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
private OnActivityResultDelegate.Mediator mActivityResultMediator = new OnActivityResultDelegate.Mediator();
private VersionGuard mVersionGuard;
private BackPressedHandler.Observer mBackPressObserver = new BackPressedHandler.Observer();
private SearchViewItem mSearchViewItem;
@Override
@@ -263,8 +256,8 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
}
private void setUpSearchMenuItem(MenuItem searchMenuItem) {
SearchViewItem searchViewItem = new SearchViewItem(this, searchMenuItem);
searchViewItem.setQueryCallback(this::submitQuery);
mSearchViewItem = new SearchViewItem(this, searchMenuItem);
mSearchViewItem.setQueryCallback(this::submitQuery);
}
private void submitQuery(String query) {
@@ -272,7 +265,11 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
EventBus.getDefault().post(QueryEvent.CLEAR);
return;
}
EventBus.getDefault().post(new QueryEvent(query));
QueryEvent event = new QueryEvent(query);
EventBus.getDefault().post(event);
if (event.shouldCollapseSearchView()) {
mSearchViewItem.collapse();
}
}
}

View File

@@ -8,6 +8,7 @@ public class QueryEvent {
public static final QueryEvent CLEAR = new QueryEvent(null);
private boolean mShouldCollapseSearchView = false;
private final String mQuery;
public QueryEvent(String query) {
@@ -17,4 +18,13 @@ public class QueryEvent {
public String getQuery() {
return mQuery;
}
public void collapseSearchView() {
mShouldCollapseSearchView = true;
}
public boolean shouldCollapseSearchView() {
return mShouldCollapseSearchView;
}
}

View File

@@ -104,6 +104,7 @@ public class CommunityFragment extends ViewPagerFragment implements BackPressedH
String query = URLEncoder.encode(event.getQuery());
String url = String.format("http://www.autojs.org/search?term=%s&in=titlesposts", query);
mWebView.loadUrl(url);
event.collapseSearchView();
}
private boolean isInPostsPage() {

View File

@@ -25,6 +25,7 @@ import com.stardust.scriptdroid.model.script.Scripts;
import com.stardust.scriptdroid.io.StorageFileProvider;
import com.stardust.scriptdroid.ui.common.ScriptLoopDialog;
import com.stardust.scriptdroid.ui.common.ScriptOperations;
import com.stardust.scriptdroid.ui.floating.EditorFloaty;
import com.stardust.scriptdroid.ui.viewmodel.ScriptList;
import com.stardust.widget.BindableViewHolder;
@@ -217,6 +218,10 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa
.show();
notifyOperated();
break;
case R.id.floating_edit:
EditorFloaty.floatingEdit(getContext(), mSelectedScriptFile);
notifyOperated();
break;
case R.id.create_shortcut:
new ScriptOperations(getContext(), this)
.createShortcut(mSelectedScriptFile);

View File

@@ -0,0 +1,122 @@
package com.stardust.scriptdroid.ui.shortcut;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.external.shortcut.Shortcut;
import com.stardust.scriptdroid.external.shortcut.ShortcutActivity;
import com.stardust.scriptdroid.model.script.ScriptFile;
import com.stardust.scriptdroid.tool.BitmapTool;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.theme.internal.DrawableTool;
import java.io.FileNotFoundException;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* Created by Stardust on 2017/10/25.
*/
public class ShortcutCreateActivity extends AppCompatActivity {
public static final String EXTRA_FILE = "file";
private static final String LOG_TAG = "ShortcutCreateActivity";
private ScriptFile mScriptFile;
private boolean mIsDefaultIcon = true;
@BindView(R.id.name)
TextView mName;
@BindView(R.id.select_icon)
ImageView mIcon;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mScriptFile = (ScriptFile) getIntent().getSerializableExtra(EXTRA_FILE);
showDialog();
}
private void showDialog() {
View view = View.inflate(this, R.layout.shortcut_create_dialog, null);
ButterKnife.bind(this, view);
mName.setText(mScriptFile.getSimplifiedName());
new ThemeColorMaterialDialogBuilder(this)
.customView(view, false)
.title(R.string.text_send_shortcut)
.positiveText(R.string.ok)
.onPositive((dialog, which) -> {
createShortcut();
finish();
})
.cancelListener(dialog -> finish())
.show();
}
@OnClick(R.id.select_icon)
void selectIcon() {
ShortcutIconSelectActivity_.intent(this)
.startForResult(21209);
}
private void createShortcut() {
Shortcut shortcut = new Shortcut(this);
if (mIsDefaultIcon) {
shortcut.iconRes(R.drawable.ic_node_js_black);
} else {
Bitmap bitmap = BitmapTool.drawableToBitmap(mIcon.getDrawable());
shortcut.icon(bitmap);
}
shortcut.name(mName.getText().toString())
.targetClass(ShortcutActivity.class)
.extras(new Intent().putExtra(CommonUtils.EXTRA_KEY_PATH, mScriptFile.getPath()))
.send();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
return;
}
String packageName = data.getStringExtra(ShortcutIconSelectActivity.EXTRA_PACKAGE_NAME);
if (packageName != null) {
try {
mIcon.setImageDrawable(getPackageManager().getApplicationIcon(packageName));
mIsDefaultIcon = false;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return;
}
Observable.fromCallable(() -> BitmapFactory.decodeStream(getContentResolver().openInputStream(data.getData())))
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe((bitmap -> {
mIcon.setImageBitmap(bitmap);
mIsDefaultIcon = false;
}), error -> {
Log.e(LOG_TAG, "decode stream", error);
});
}
}

View File

@@ -0,0 +1,140 @@
package com.stardust.scriptdroid.ui.shortcut;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.ui.BaseActivity;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* Created by Stardust on 2017/10/25.
*/
@EActivity(R.layout.activity_shortcut_icon_select)
public class ShortcutIconSelectActivity extends BaseActivity {
public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
@ViewById(R.id.apps)
RecyclerView mApps;
private PackageManager mPackageManager;
private List<AppItem> mAppList = new ArrayList<>();
@AfterViews
void setupViews() {
mPackageManager = getPackageManager();
setToolbarAsBack(getString(R.string.text_select_icon));
setupApps();
}
private void setupApps() {
mApps.setAdapter(new AppsAdapter());
mApps.setLayoutManager(new GridLayoutManager(this, 5));
loadApps();
}
private void loadApps() {
List<ApplicationInfo> packages = mPackageManager.getInstalledApplications(PackageManager.GET_META_DATA);
Observable.fromIterable(packages)
.observeOn(Schedulers.computation())
.filter(appInfo -> appInfo.icon != 0)
.map(AppItem::new)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(icon -> {
mAppList.add(icon);
mApps.getAdapter().notifyItemInserted(mAppList.size() - 1);
});
}
private void selectApp(AppItem appItem) {
setResult(RESULT_OK, new Intent()
.putExtra(EXTRA_PACKAGE_NAME, appItem.info.packageName));
finish();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_shortcut_icon_select, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
startActivityForResult(new Intent(Intent.ACTION_GET_CONTENT)
.setType("image/*"), 11209);
return true;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
setResult(RESULT_OK, data);
finish();
}
}
private class AppItem {
Drawable icon;
ApplicationInfo info;
public AppItem(ApplicationInfo info) {
this.info = info;
icon = info.loadIcon(mPackageManager);
}
}
private class AppIconViewHolder extends RecyclerView.ViewHolder {
ImageView icon;
public AppIconViewHolder(View itemView) {
super(itemView);
icon = (ImageView) itemView;
icon.setOnClickListener(v -> selectApp(mAppList.get(getAdapterPosition())));
}
}
private class AppsAdapter extends RecyclerView.Adapter<AppIconViewHolder> {
@Override
public AppIconViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new AppIconViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.app_icon_list_item, parent, false));
}
@Override
public void onBindViewHolder(AppIconViewHolder holder, int position) {
holder.icon.setImageDrawable(mAppList.get(position).icon);
}
@Override
public int getItemCount() {
return mAppList.size();
}
}
}

View File

@@ -69,4 +69,10 @@ public class SearchViewItem implements MenuItemCompat.OnActionExpandListener, Se
public boolean onQueryTextChange(String newText) {
return false;
}
public void collapse() {
mSearchMenuItem.collapseActionView();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="4dp"/>
<solid android:color="#727379"/>
</shape>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:title="@string/_app_name"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/apps"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"/>
</LinearLayout>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:padding="8dp">
</ImageView>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:id="@+id/select_icon"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="16dp"
android:background="@drawable/shortcut_create_dialog_icon_bg"
android:padding="12dp"
android:src="@drawable/ic_add_white_48dp"/>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<android.support.design.widget.TextInputEditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/text_name"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>

View File

@@ -12,6 +12,9 @@
<item
android:id="@+id/delete"
android:title="@string/text_delete"/>
<item
android:id="@+id/floating_edit"
android:title="@string/text_floating_edit"/>
<item
android:id="@+id/create_shortcut"

View File

@@ -0,0 +1,10 @@
<?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/action_select_image"
android:icon="@drawable/ic_insert_photo_white_48dp"
android:title="@string/text_select_image"
app:showAsAction="always"/>
</menu>

View File

@@ -45,7 +45,7 @@
<string name="text_start_running">开始运行</string>
<string name="text_open_by_other_apps">用其他应用打开</string>
<string name="text_rename">重命名</string>
<string name="text_send_shortcut">创建桌面快捷方式</string>
<string name="text_send_shortcut">创建快捷方式</string>
<string name="text_already_create">已创建</string>
<string name="text_delete">删除</string>
<string name="text_already_delete">已删除</string>
@@ -263,6 +263,8 @@
<string name="apk_builder_clean">清理临时文件</string>
<string name="text_source_file_path">脚本文件路径</string>
<string name="text_search">搜索</string>
<string name="text_floating_edit">悬浮编辑</string>
<string name="text_select_icon">选择图标</string>
<string-array name="ad_showing_mode_keys">