mirror of
https://github.com/ActivityLauncher/ActivityLauncher.git
synced 2026-08-17 12:53:23 +00:00
feature: filtering of activity list
This commit is contained in:
parent
0bef8138b6
commit
12d143155f
12 changed files with 157 additions and 28 deletions
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.szalkowski.activitylauncher"
|
||||
android:versionCode="14"
|
||||
android:versionName="1.8.2" >
|
||||
android:versionCode="15"
|
||||
android:versionName="1.9.0" >
|
||||
|
||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseExpandableListAdapter;
|
||||
import android.widget.Filter;
|
||||
import android.widget.Filterable;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
|
@ -15,10 +17,34 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class AllTasksListAdapter extends BaseExpandableListAdapter {
|
||||
public class AllTasksListAdapter extends BaseExpandableListAdapter implements Filterable {
|
||||
private PackageManager pm;
|
||||
private List<MyPackageInfo> packages;
|
||||
private LayoutInflater inflater;
|
||||
private List<MyPackageView> filtered;
|
||||
|
||||
private class MyPackageView {
|
||||
private class Child {
|
||||
MyActivityInfo child;
|
||||
long id;
|
||||
}
|
||||
MyPackageInfo parent;
|
||||
List<Child> children;
|
||||
long id;
|
||||
|
||||
MyPackageView(MyPackageInfo parent, long id) {
|
||||
this.parent = parent;
|
||||
this.id = id;
|
||||
this.children = new ArrayList<>();
|
||||
}
|
||||
|
||||
void add(MyActivityInfo activity, long id) {
|
||||
Child child = new Child();
|
||||
child.child = activity;
|
||||
child.id = id;
|
||||
this.children.add(child);
|
||||
}
|
||||
}
|
||||
|
||||
AllTasksListAdapter(Context context) {
|
||||
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
|
@ -46,16 +72,46 @@ public class AllTasksListAdapter extends BaseExpandableListAdapter {
|
|||
}
|
||||
|
||||
Collections.sort(this.packages);
|
||||
this.filtered = createFilterView("");
|
||||
|
||||
}
|
||||
|
||||
private List<MyPackageView> createFilterView(String query) {
|
||||
String q = query.toLowerCase();
|
||||
List<MyPackageView> result = new ArrayList<>();
|
||||
for (int j = 0; j < this.packages.size(); ++j) {
|
||||
MyPackageInfo parent = this.packages.get(j);
|
||||
MyPackageView entry = new MyPackageView(parent, j);
|
||||
|
||||
for (int i = 0; i < parent.getActivitiesCount(); ++i) {
|
||||
MyActivityInfo child = parent.getActivity(i);
|
||||
if (child.name.toLowerCase().contains(q) ||
|
||||
child.component_name.flattenToString().toLowerCase().contains(q) ||
|
||||
child.icon_resource_name != null && child.icon_resource_name.toLowerCase().contains(q)) {
|
||||
entry.add(child, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!entry.children.isEmpty() ||
|
||||
parent.name.toLowerCase().contains(q) ||
|
||||
parent.package_name.toLowerCase().contains(q) ||
|
||||
parent.icon_resource_name != null && parent.icon_resource_name.contains(q)
|
||||
) {
|
||||
result.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getChild(int groupPosition, int childPosition) {
|
||||
return this.packages.get(groupPosition).getActivity(childPosition);
|
||||
return this.filtered.get(groupPosition).children.get(childPosition).child;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChildId(int groupPosition, int childPosition) {
|
||||
return childPosition;
|
||||
return this.filtered.get(groupPosition).children.get(childPosition).id;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -77,22 +133,22 @@ public class AllTasksListAdapter extends BaseExpandableListAdapter {
|
|||
|
||||
@Override
|
||||
public int getChildrenCount(int groupPosition) {
|
||||
return this.packages.get(groupPosition).getActivitiesCount();
|
||||
return this.filtered.get(groupPosition).children.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGroup(int groupPosition) {
|
||||
return this.packages.get(groupPosition);
|
||||
return this.filtered.get(groupPosition).parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGroupCount() {
|
||||
return this.packages.size();
|
||||
return this.filtered.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getGroupId(int groupPosition) {
|
||||
return groupPosition;
|
||||
return this.filtered.get(groupPosition).id;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -119,4 +175,25 @@ public class AllTasksListAdapter extends BaseExpandableListAdapter {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter getFilter() {
|
||||
return new Filter() {
|
||||
@Override
|
||||
protected FilterResults performFiltering(CharSequence constraint) {
|
||||
List<MyPackageView> result = createFilterView(constraint.toString());
|
||||
FilterResults wrapped = new FilterResults();
|
||||
wrapped.values = result;
|
||||
wrapped.count = result.size();
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void publishResults(CharSequence constraint, FilterResults results) {
|
||||
if (results != null) {
|
||||
filtered = (List<MyPackageView>) results.values;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import android.widget.ExpandableListAdapter;
|
|||
import android.widget.ExpandableListView;
|
||||
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
|
||||
import android.widget.ExpandableListView.OnChildClickListener;
|
||||
import android.widget.Filter;
|
||||
import android.widget.Filterable;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
|
@ -22,8 +24,12 @@ import androidx.fragment.app.Fragment;
|
|||
|
||||
import org.thirdparty.LauncherIconCreator;
|
||||
|
||||
public class AllTasksListFragment extends Fragment implements AllTasksListAsyncProvider.Listener<AllTasksListAdapter> {
|
||||
protected ExpandableListView list;
|
||||
public class AllTasksListFragment extends Fragment implements AllTasksListAsyncProvider.Listener<AllTasksListAdapter>, Filterable {
|
||||
private ExpandableListView list;
|
||||
|
||||
AllTasksListFragment() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
|
|
@ -41,6 +47,7 @@ public class AllTasksListFragment extends Fragment implements AllTasksListAsyncP
|
|||
return false;
|
||||
}
|
||||
});
|
||||
this.list.setTextFilterEnabled(true);
|
||||
|
||||
AllTasksListAsyncProvider provider = new AllTasksListAsyncProvider(getActivity(), this);
|
||||
provider.execute();
|
||||
|
|
@ -129,11 +136,21 @@ public class AllTasksListFragment extends Fragment implements AllTasksListAsyncP
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onProviderFininshed(AsyncProvider<AllTasksListAdapter> task, AllTasksListAdapter value) {
|
||||
public void onProviderFinished(AsyncProvider<AllTasksListAdapter> task, AllTasksListAdapter value) {
|
||||
try {
|
||||
this.list.setAdapter(value);
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(getActivity(), R.string.error_tasks, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter getFilter() {
|
||||
AllTasksListAdapter adapter = (AllTasksListAdapter) this.list.getExpandableListAdapter();
|
||||
if (adapter != null) {
|
||||
return adapter.getFilter();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ public abstract class AsyncProvider<ReturnType> extends AsyncTask<Void, Integer,
|
|||
protected void onPostExecute(ReturnType result) {
|
||||
super.onPostExecute(result);
|
||||
if (this.listener != null) {
|
||||
this.listener.onProviderFininshed(this, result);
|
||||
this.listener.onProviderFinished(this, result);
|
||||
}
|
||||
|
||||
if (this.progress != null) {
|
||||
|
|
@ -70,7 +70,7 @@ public abstract class AsyncProvider<ReturnType> extends AsyncTask<Void, Integer,
|
|||
}
|
||||
|
||||
public interface Listener<ReturnType> {
|
||||
void onProviderFininshed(AsyncProvider<ReturnType> task, ReturnType value);
|
||||
void onProviderFinished(AsyncProvider<ReturnType> task, ReturnType value);
|
||||
}
|
||||
|
||||
class Updater {
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ public class IconPickerDialogFragment extends DialogFragment implements IconList
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onProviderFininshed(AsyncProvider<IconListAdapter> task,
|
||||
IconListAdapter value) {
|
||||
public void onProviderFinished(AsyncProvider<IconListAdapter> task,
|
||||
IconListAdapter value) {
|
||||
try {
|
||||
this.grid.setAdapter(value);
|
||||
} catch (Exception e) {
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ public class IconPickerFragment extends Fragment implements IconListAsyncProvide
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onProviderFininshed(AsyncProvider<IconListAdapter> task,
|
||||
IconListAdapter value) {
|
||||
public void onProviderFinished(AsyncProvider<IconListAdapter> task,
|
||||
IconListAdapter value) {
|
||||
try {
|
||||
this.grid.setAdapter(value);
|
||||
} catch (Exception e) {
|
||||
|
|
|
|||
|
|
@ -9,14 +9,17 @@ import android.os.Build;
|
|||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Filter;
|
||||
import android.widget.Filterable;
|
||||
import android.widget.SearchView;
|
||||
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
public class MainActivity extends FragmentActivity {
|
||||
|
||||
protected final String LOG = "de.szalkowski.activitylauncher.MainActivity";
|
||||
private final String LOG = "de.szalkowski.activitylauncher.MainActivity";
|
||||
private Filterable filterTarget = null;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
|
@ -28,9 +31,10 @@ public class MainActivity extends FragmentActivity {
|
|||
dialog.show(getSupportFragmentManager(), "DisclaimerDialogFragment");
|
||||
}
|
||||
|
||||
Fragment fragment = new AllTasksListFragment();
|
||||
AllTasksListFragment fragment = new AllTasksListFragment();
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.container, fragment).commit();
|
||||
filterTarget = fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -57,9 +61,33 @@ public class MainActivity extends FragmentActivity {
|
|||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.main, menu);
|
||||
|
||||
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
|
||||
searchView.setQueryHint(this.getText(R.string.filter_hint));
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
onFilter(query);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
onFilter(newText);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onFilter(String query) {
|
||||
Filter filter = filterTarget.getFilter();
|
||||
if (filter != null) {
|
||||
filter.filter(query);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/search"
|
||||
android:title="@string/action_filter"
|
||||
android:icon="@android:drawable/ic_menu_search"
|
||||
android:showAsAction="collapseActionView|ifRoom"
|
||||
android:actionViewClass="android.widget.SearchView" />
|
||||
<item
|
||||
android:id="@+id/action_view_source"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/action_view_source"></item>
|
||||
android:title="@string/action_view_source" />
|
||||
<item
|
||||
android:id="@+id/action_view_translation"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/action_view_translation"></item>
|
||||
android:title="@string/action_view_translation" />
|
||||
<item
|
||||
android:id="@+id/action_view_bugs"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/action_view_bugs"></item>
|
||||
android:title="@string/action_view_bugs" />
|
||||
</menu>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<resources>
|
||||
<string name="url_source" translatable="false">https://github.com/butzist/ActivityLauncher</string>
|
||||
<string name="url_translation" translatable="false">http://crowdin.net/project/activitylauncher/invite</string>
|
||||
<string name="url_translation" translatable="false">https://crowdin.net/project/activitylauncher/invite</string>
|
||||
<string name="url_bugs" translatable="false">https://github.com/butzist/ActivityLauncher/issues</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -28,4 +28,6 @@
|
|||
<string name="action_view_translation">Help Translating!</string>
|
||||
<string name="action_view_bugs">Report A Problem</string>
|
||||
<string name="error_no_default_activity">Package does not have a default activity - try to select one explicitly</string>
|
||||
<string name="action_filter">Filter...</string>
|
||||
<string name="filter_hint">package/action</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ buildscript {
|
|||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
classpath 'com.android.tools.build:gradle:3.5.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
|
@ -1,6 +1,6 @@
|
|||
#Sat Apr 20 11:06:49 CEST 2019
|
||||
#Thu Oct 31 11:15:14 CET 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue