{"id":18538967,"url":"https://github.com/ramotion/direct-select-android","last_synced_at":"2025-04-12T19:45:40.765Z","repository":{"id":144130602,"uuid":"113307522","full_name":"Ramotion/direct-select-android","owner":"Ramotion","description":":octocat: ≡ DirectSelect is a selection widget with an ethereal, full-screen modal popup displaying the available choices when the widget is interact with.","archived":false,"fork":false,"pushed_at":"2020-04-06T13:34:44.000Z","size":6278,"stargazers_count":530,"open_issues_count":3,"forks_count":62,"subscribers_count":23,"default_branch":"master","last_synced_at":"2025-04-03T22:09:55.687Z","etag":null,"topics":["android","java","library"],"latest_commit_sha":null,"homepage":"https://www.ramotion.com/android-app-development-ui-library-for-selecting-items-from-a-list/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ramotion.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-12-06T11:25:59.000Z","updated_at":"2025-02-01T06:24:19.000Z","dependencies_parsed_at":"2023-03-25T20:03:07.999Z","dependency_job_id":null,"html_url":"https://github.com/Ramotion/direct-select-android","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ramotion%2Fdirect-select-android","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ramotion%2Fdirect-select-android/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ramotion%2Fdirect-select-android/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ramotion%2Fdirect-select-android/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ramotion","download_url":"https://codeload.github.com/Ramotion/direct-select-android/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248625490,"owners_count":21135513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","java","library"],"created_at":"2024-11-06T19:45:41.446Z","updated_at":"2025-04-12T19:45:40.744Z","avatar_url":"https://github.com/Ramotion.png","language":"Java","readme":"\u003ca href=\"https://www.ramotion.com/agency/app-development/?utm_source=gthb\u0026utm_medium=repo\u0026utm_campaign=direct-select-android\"\u003e\u003cimg src=\"https://github.com/Ramotion/folding-cell/blob/master/header.png\"\u003e\u003c/a\u003e\n\n\u003ca href=\"https://github.com/Ramotion/direct-select-android\"\u003e\n\u003cimg align=\"left\" src=\"https://github.com/Ramotion/direct-select-android/blob/master/direct_select_preview.gif\" width=\"480\" height=\"360\" /\u003e\u003c/a\u003e\n\n\u003cp\u003e\u003ch1 align=\"left\"\u003eDIRECT SELECT [JAVA]\u003c/h1\u003e\u003c/p\u003e\n\n\u003ch4\u003eSelection widget with an ethereal, full-screen modal popup displaying the available choices\u003c/h4\u003e\n\n\n___\n\n\n\u003cp\u003e\u003ch6\u003eWe specialize in the designing and coding of custom UI for Mobile Apps and Websites.\u003c/h6\u003e\n\u003ca href=\"https://www.ramotion.com/agency/app-development/?utm_source=gthb\u0026utm_medium=repo\u0026utm_campaign=direct-select-android\"\u003e\n\u003cimg src=\"https://github.com/ramotion/gliding-collection/raw/master/contact_our_team@2x.png\" width=\"187\" height=\"34\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003ch6\u003eStay tuned for the latest updates:\u003c/h6\u003e\n\u003ca href=\"https://goo.gl/rPFpid\" \u003e\n\u003cimg src=\"https://i.imgur.com/ziSqeSo.png/\" width=\"156\" height=\"28\"\u003e\u003c/a\u003e\u003c/p\u003e\n\nInspired by [Virgil Pana](https://dribbble.com/virgilpana) [shot](https://dribbble.com/shots/3876250-DirectSelect-Dropdown-ux)\n\n## Requirements\n - Android 4.0 IceCreamSandwich (API lvl 14) or greater\n - Your favorite IDE\n## Installation\nJust download the package from [here](http://central.maven.org/maven2/com/ramotion/directselect/direct-select/0.1.1/direct-select-0.1.1.aar) and add it to your project classpath, or use it as dependency in your build tool:\n - Gradle:\n```groovy\n'com.ramotion.directselect:direct-select:0.1.1'\n```\n - SBT:\n```scala\nlibraryDependencies += \"com.ramotion.directselect\" % \"direct-select\" % \"0.1.1\"\n```\n - Maven:\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003ecom.ramotion.directselect\u003c/groupId\u003e\n\t\u003cartifactId\u003edirect-select\u003c/artifactId\u003e\n\t\u003cversion\u003e0.1.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n## Basic usage\nBasic usage assumes a simple configuration through xml layout without writing program code, but this doesn't provide the possibility to create cells with custom content layout for your lists and pickers.\nSo, all you need is two elements in your layout:\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cFrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:ds=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\"com.ramotion.directselect.examples.basic.BasicExampleActivity\"\u003e\n\n   \u003ccom.ramotion.directselect.DSListView\n        android:id=\"@+id/ds_picker\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@color/ds_list_bg\"\n        android:visibility=\"invisible\"\n        ds:cell_font_size=\"8sp\"\n        ds:data_array=\"@array/months\"\n        ds:picker_box_view=\"@id/picker_box\"\n        ds:scale_animations=\"true\"\n        ds:scale_animations_factor=\"1.3\"\n        ds:scale_animations_pivot_center=\"false\"\n        ds:selected_index=\"2\"\n        ds:selector_background=\"@color/ds_list_selector_bg\" /\u003e\n\n    \u003ccom.ramotion.directselect.DSDefaultPickerBox\n        android:id=\"@+id/picker_box\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"260dp\"\n        android:background=\"@color/ds_picker_box_bg\"\n        android:padding=\"15dp\" /\u003e\n\n\u003c/FrameLayout\u003e\n```\n`DSListView` represents a list with options for the picker that shows up when the user touches a `DSDefaultPickerBox` element and hides when the user removes his finger from the screen.  `DSListView` has a couple of custom attributes, some of them are required, some not, here is a list:\n - **`data_array`** is a required reference to your selector options represented as array of strings in application resources.\n - **`picker_box_view`** is a required reference to implemented picker box element, you can use default implementation provided by the library `DSDefaultPickerBox` or you can implement your own as shown in the advanced usage example in this repository.\n - **`selector_background`**  is a drawable or color responsible for a highlighting of selector position when `DSListView` is shown on the screen. Using the same background as in your PickerBox element you can achieve a pretty nice and clean effect.\n - **`scale_animations`** is a boolean that turns on/off scale animations of the selected item. Try it.\n - **`scale_animations_factor`** is a float value that defines max scale ratio for scaling animation\n - **`scale_animations_pivot_center`** is a boolean that moves pivot point of scale animations to center of your element instead of default left aligned position.\n - **`selected_index`** is an integer that represents initially selected option.\n\n## Advanced usage\nHere everything is more complicated. Let's start from creating layout files.\n 1. First of all we need to implement our custom cell layout, in separate xml file, eg `advanced_example_country_cell.xml`:\n ```xml\n \u003cRelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/custom_cell_root\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:layout_centerVertical=\"true\"\u003e\n\n    \u003cImageView\n        android:id=\"@+id/custom_cell_image\"\n        android:layout_width=\"30dp\"\n        android:layout_height=\"30dp\"\n        android:layout_alignParentLeft=\"true\"\n        android:layout_alignParentStart=\"true\"\n        android:layout_centerVertical=\"true\"\n        android:layout_margin=\"10dp\"\n        android:contentDescription=\"@string/cell_image\"\n        android:scaleType=\"centerCrop\" /\u003e\n\n    \u003cTextView\n        android:id=\"@+id/custom_cell_text\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerVertical=\"true\"\n        android:layout_toEndOf=\"@id/custom_cell_image\"\n        android:layout_toRightOf=\"@id/custom_cell_image\" /\u003e\n\n\u003c/RelativeLayout\u003e\n```\n2. Now we need to create a layout for our cell in the list view, `advanced_example_country_list_item.xml`- it just wraps our newly created cell with `FrameLayout` for correct element animations and positioning inside the list view.\n```xml\n\u003cFrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:clipChildren=\"false\"\n    android:clipToPadding=\"false\"\n    android:paddingLeft=\"20dp\"\n    android:paddingRight=\"20dp\"\u003e\n\n    \u003cinclude\n        layout=\"@layout/advanced_example_country_cell\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" /\u003e\n\n\u003c/FrameLayout\u003e\n```\n3.  Third step - creation of our custom picker box layout, a new file named `advanced_example_country_picker_box.xml` that contains our custom cell layout, and inserts an additional custom elements that must appear only in picker box, like the direction arrows in our example.\n```xml\n\u003cRelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@drawable/ds_bg_picker_box\"\n    android:paddingLeft=\"20dp\"\n    android:paddingRight=\"20dp\"\u003e\n\n    \u003cinclude\n        layout=\"@layout/advanced_example_country_cell\"\n        android:layout_height=\"wrap_content\"\n        android:layout_width=\"wrap_content\" /\u003e\n\n    \u003cImageView\n        android:id=\"@+id/picker_box_arrows\"\n        android:layout_width=\"30dp\"\n        android:layout_height=\"30dp\"\n        android:layout_alignParentEnd=\"true\"\n        android:layout_alignParentRight=\"true\"\n        android:layout_centerVertical=\"true\"\n        android:layout_marginEnd=\"10dp\"\n        android:layout_marginRight=\"10dp\"\n        android:alpha=\"0.25\"\n        android:contentDescription=\"@string/picker_box_arrows_icon\"\n        android:scaleType=\"fitCenter\"\n        android:src=\"@drawable/ds_picker_box_arrows\" /\u003e\n\n\u003c/RelativeLayout\u003e\n```  \n4. Finally, we need to write some code. First of all - we need to prepare a dataset, our cell contains two items - a title and image, so we can't use the default `data_array` attribute from the basic example. Our structure can be represented by plain old java object with two appropriate fields.\n```java\npublic class AdvancedExampleCountryPOJO {\n    private String title;\n    private int icon;\n\n    public AdvancedExampleCountryPOJO(String title, int icon) {\n        this.title = title;\n        this.icon = icon;\n    }\n\n    public static List\u003cAdvancedExampleCountryPOJO\u003e getExampleDataset() {\n        return Arrays.asList(\n                new AdvancedExampleCountryPOJO(\"Russian Federation\", R.drawable.ds_countries_ru),\n                new AdvancedExampleCountryPOJO(\"Canada\", R.drawable.ds_countries_ca),\n                new AdvancedExampleCountryPOJO(\"United States of America\", R.drawable.ds_countries_us),\n                new AdvancedExampleCountryPOJO(\"China\", R.drawable.ds_countries_cn),\n                new AdvancedExampleCountryPOJO(\"Brazil\", R.drawable.ds_countries_br),\n                new AdvancedExampleCountryPOJO(\"Australia\", R.drawable.ds_countries_au),\n                new AdvancedExampleCountryPOJO(\"India\", R.drawable.ds_countries_in),\n                new AdvancedExampleCountryPOJO(\"Argentina\", R.drawable.ds_countries_ar),\n                new AdvancedExampleCountryPOJO(\"Kazakhstan\", R.drawable.ds_countries_kz),\n                new AdvancedExampleCountryPOJO(\"Algeria\", R.drawable.ds_countries_dz)\n        );\n    }\n\n    // getters, setters, equal, hashcode, etc.\n}\n```\n5. Now, to more complex things - we need to somehow provide our dataset to `DSListView`, for this purpose in Android we have a `android.widget.ArrayAdapter` class, so we need a custom implementation to map data from our POJO to the actual cell described earlier:\n```java\npublic class AdvancedExampleCountryAdapter extends ArrayAdapter\u003cAdvancedExampleCountryPOJO\u003e {\n    private List\u003cAdvancedExampleCountryPOJO\u003e items;\n    private Context context;\n\n    public AdvancedExampleCountryAdapter(@NonNull Context context, int resource, @NonNull List\u003cAdvancedExampleCountryPOJO\u003e objects) {\n        super(context, resource, objects);\n        this.items = objects;\n        this.context = context;\n    }\n\n    @Override\n    public long getItemId(int position) {\n        return position;\n    }\n\n    @Override\n    public boolean hasStableIds() {\n        return true;\n    }\n\n    @Override\n    public int getCount() {\n        return items.size();\n    }\n\n    @NonNull\n    @Override\n    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {\n        AdvancedExampleCountryAdapter.ViewHolder holder;\n\n        if (null == convertView) {\n            LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);\n            assert vi != null;\n            convertView = vi.inflate(R.layout.advanced_example_country_list_item, parent, false);\n            holder = new AdvancedExampleCountryAdapter.ViewHolder();\n            holder.text = convertView.findViewById(R.id.custom_cell_text);\n            holder.icon = convertView.findViewById(R.id.custom_cell_image);\n            convertView.setTag(holder);\n        } else {\n            holder = (AdvancedExampleCountryAdapter.ViewHolder) convertView.getTag();\n        }\n        if (null != holder) {\n            holder.text.setText(items.get(position).getTitle());\n            holder.icon.setImageResource(items.get(position).getIcon());\n        }\n        return convertView;\n    }\n\n    private class ViewHolder {\n        TextView text;\n        ImageView icon;\n    }\n}\n\n```\n6. Almost done, but before we put it all together, there is one more thing. We almost forgot about our custom picker box to map the selected cell from the list view to the actual displayed picker. So, we need to implement simple view that inflates our layout for the picker box described earlier. To guarantee correctness, work must extend the `DSAbstractPickerBox` class and implement some abstract methods:\n```java\npublic class AdvancedExampleCountryPickerBox extends DSAbstractPickerBox\u003cAdvancedExampleCountryPOJO\u003e {\n    private TextView text;\n    private ImageView icon;\n    private View cellRoot;\n\n    public AdvancedExampleCountryPickerBox(@NonNull Context context) {\n        this(context, null);\n    }\n\n    public AdvancedExampleCountryPickerBox(@NonNull Context context,\n\t\t\t\t\t\t\t\t\t\t   @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public AdvancedExampleCountryPickerBox(@NonNull Context context,\n\t\t\t\t\t\t\t\t\t\t   @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(context);\n    }\n\n    private void init(@NonNull Context context) {\n        LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);\n        assert mInflater != null;\n        mInflater.inflate(R.layout.advanced_example_country_picker_box, this, true);\n    }\n\n    @Override\n    protected void onFinishInflate() {\n        super.onFinishInflate();\n        this.text = findViewById(R.id.custom_cell_text);\n        this.icon = findViewById(R.id.custom_cell_image);\n        this.cellRoot = findViewById(R.id.custom_cell_root);\n    }\n\n    @Override\n    public void onSelect(AdvancedExampleCountryPOJO selectedItem, int selectedIndex) {\n        this.text.setText(selectedItem.getTitle());\n        this.icon.setImageResource(selectedItem.getIcon());\n    }\n\n    @Override\n    public View getCellRoot() {\n        return this.cellRoot;\n    }\n}\n```\n7. Finally - put all parts together in the main activity layout and write some code in `MainActivity`:\n```java\npublic class AdvancedExampleActivity extends AppCompatActivity {\n\n    @SuppressLint(\"ClickableViewAccessibility\")\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.advanced_example_activity);\n\n\t\t// Prepare dataset\n        List\u003cAdvancedExampleCountryPOJO\u003e exampleDataSet = AdvancedExampleCountryPOJO.getExampleDataset();\n\n\t\t// Create adapter with our dataset\n        ArrayAdapter\u003cAdvancedExampleCountryPOJO\u003e adapter = new AdvancedExampleCountryAdapter(\n                this, R.layout.advanced_example_country_list_item, exampleDataSet);\n\n\t\t// Set adapter to our DSListView\n        DSListView\u003cAdvancedExampleCountryPOJO\u003e pickerView = findViewById(R.id.ds_county_list);\n        pickerView.setAdapter(adapter);\n\n    }\n}\n```\nThat's all. There are still some unmentioned features, like the possibility to change the size and position of the list view and the possibility to change default cell text appearance through `cell-font-size` settings or through applying your custom style.\nFull examples with some comments and explanations can be found in this repository. Feel free to report bugs and ask questions.\n\n\u003cbr\u003e\n\n## 📄 License\n\nDirect Select Android is released under the MIT license.\nSee [LICENSE](./LICENSE) for details.\n\nThis library is a part of a \u003ca href=\"https://github.com/Ramotion/android-ui-animation-components-and-libraries\"\u003e\u003cb\u003eselection of our best UI open-source projects\u003c/b\u003e\u003c/a\u003e\n\nIf you use the open-source library in your project, please make sure to credit and backlink to www.ramotion.com\n\n## 📱 Get the Showroom App for Android to give it a try\nTry this UI component and more like this in our Android app. Contact us if interested.\n\n\u003ca href=\"https://play.google.com/store/apps/details?id=com.ramotion.showroom\" \u003e\n\u003cimg src=\"https://raw.githubusercontent.com/Ramotion/react-native-circle-menu/master/google_play@2x.png\" width=\"104\" height=\"34\"\u003e\u003c/a\u003e\n\n\u003ca href=\"https://www.ramotion.com/agency/app-development/?utm_source=gthb\u0026utm_medium=repo\u0026utm_campaign=direct-select-android\"\u003e\n\u003cimg src=\"https://github.com/ramotion/gliding-collection/raw/master/contact_our_team@2x.png\" width=\"187\" height=\"34\"\u003e\u003c/a\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Framotion%2Fdirect-select-android","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Framotion%2Fdirect-select-android","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Framotion%2Fdirect-select-android/lists"}