Customizable Android full screen image viewer for Fresco library supporting "pinch to zoom" and "swipe to dismiss" gestures. Made by Stfalcon

Overview

This project is no longer supported. If you're able to switch from Fresco to any other library that works with the Android's ImageView, please migrate to the StfalconImageViewer which is a better version of the FrescoImageViewer. Otherwise, you can still use the latest version of this library. Anyway, PRs are welcome!

FrescoImageViewer

codebeat badge Download

Simple customizable full screen image viewer for Fresco library that includes "pinch to zoom" and "swipe to dismiss" gestures. Based on PhotoDraweeView by ongakuer.

alt tag

Who we are

Need iOS and Android apps, MVP development or prototyping? Contact us via [email protected]. We develop software since 2009, and we're known experts in this field. Check out our portfolio and see more libraries from stfalcon-studio.

Requirements

  • Fresco v.0.12.0 and higher
  • SDK 14 and and higher

Demo Application

Get it on Google Play

Usage

Simple usage

All you need to show a viewer is pass the context, start position and List or String[] into builder and call show().

new ImageViewer.Builder(context, list)
        .setStartPosition(startPosition)
        .show();

Custom objects

But what if in your application images are represented not only with urls? For example, you have object with url and description? You'll have to convert it to list of Strings and only then pass it to viewer, right? No, it's unnecessary! With ImageViewer.Formatter you can pass list of your custom images to viewer and simply write a rule for url extracting:

List<CustomImage> images = getImages();
new ImageViewer.Builder<>(this, images)
        .setFormatter(new ImageViewer.Formatter<CustomImage>() {
            @Override
            public String format(CustomImage customImage) {
                return customImage.getUrl();
            }
        })
        .show();

If formatter isn't passed, Object.toString() will be used for image formatting as default behavior.

Piece of cake! 🍰 😉

Reminder

Don't forget to initialize Fresco in your Application class:

Fresco.initialize(this);

And if you expect to open really large images, use configuration below for better performance:

ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this)
    .setProgressiveJpegConfig(new SimpleProgressiveJpegConfig())
    .setResizeAndRotateEnabledForNetwork(true)
    .setDownsampleEnabled(true)
    .build();
Fresco.initialize(this, config);

Customizing

You can also customize a viewer to fit your needs.

Background

Use setBackgroundColorRes(colorRes) or setBackgroundColor(colorInt) to set color for fading background.

Custom overlay view

If you need some content over the image (e.g. sharing or download button, description, numeration etc.) you can set your custom view using setOverlayView(customView) and bind it with viewer through ImageViewer.OnImageChangeListener.

Custom drawee hierarchy

Of course, according to Fresco flexibility, you can use your custom GenericDraweeHierarchy. To do this you simply need to create GenericDraweeHierarchyBuilder and pass it into builder:

GenericDraweeHierarchyBuilder hierarchyBuilder = GenericDraweeHierarchyBuilder.newInstance(getResources())
        .setFailureImage(R.drawable.failureDrawable)
        .setProgressBarImage(R.drawable.progressBarDrawable)
        .setPlaceholderImage(R.drawable.placeholderDrawable);

builder.setCustomDraweeHierarchyBuilder(hierarchyBuilder)

But there is a limitation: default ScaleType in hierarchy is ScaleType.FIT_CENTER, so custom value will be ignored

Custom image requests

For rare cases like post-processing or bitmap resizing you need to use your custom ImageRequestBuilder. Create it with ImageViewer.createImageRequestBuilder() and after configuration pass it to viewer through setCustomImageRequestBuilder(ImageRequestBuilder).

builder.setCustomImageRequestBuilder(
            ImageViewer.createImageRequestBuilder()
                    .setPostprocessor(new GrayscalePostprocessor()));

Image margin

Simply add margins between images with dimens with setImageMargin(context, dimen) or in px using setImageMarginPx(marginPx).

Container padding

Overlay image hides part of image? Set container padding with dimens using setContainerPadding(context, start, top, end, bottom) or setContainerPadding(context, dimean) for all sides at once. For setting padding in pixels, just use setContainerPaddingPx(...) method.

Status bar visibility

To show/hide status bar in view property you can set hideStatusBar(boolean) in builder. The default value is true.

Gestures disabling

If you need to disable some of gestures - do it using allowSwipeToDismiss(boolean) and allowZooming(boolean) accordingly.

Here is an example that sets all the possible options:

new ImageViewer.Builder<>(this, images)
        .setStartPosition(startPosition)
        .hideStatusBar(false)
        .allowZooming(true)
        .allowSwipeToDismiss(true)
        .setBackgroundColorRes(colorRes)
        //.setBackgroundColor(color)
        .setImageMargin(margin)
        //.setImageMarginPx(marginPx)
        .setContainerPadding(this, dimen)
        //.setContainerPadding(this, dimenStart, dimenTop, dimenEnd, dimenBottom)
        //.setContainerPaddingPx(padding)
        //.setContainerPaddingPx(start, top, end, bottom)
        .setCustomImageRequestBuilder(imageRequestBuilder)
        .setCustomDraweeHierarchyBuilder(draweeHierarchyBuilder)
        .setImageChangeListener(imageChangeListener)
        .setOnDismissListener(onDismissListener)
        .setOverlayView(overlayView)
        .show();

With this possibilities you can achieve something like this:

alt tag

You can take a look at sample project for more information.

Install

Download via Gradle:

compile 'com.github.stfalcon:frescoimageviewer:0.5.0'

or Maven:

<dependency>
  <groupId>com.github.stfalcon</groupId>
  <artifactId>frescoimageviewer</artifactId>
  <version>0.5.0</version>
  <type>pom</type>
</dependency>

Changelog

See the changelog to be aware of latest improvements and fixes.

License

Copyright (C) 2017 stfalcon.com

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Comments
  • Small lags when flipping

    Small lags when flipping

    HI, Alexander! I have a small problem: When viewing a large number of images(15 urls), I have a lags when flippin photo.

    Init fresco:

        public void setupFresco() {
            ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
            ImagePipelineConfig imagePipelineConfig = ImagePipelineConfig
                    .newBuilder(getApplicationContext())
                    .setBitmapMemoryCacheParamsSupplier(new FrescoMemoryCashHelper(activityManager))
                    .build();
            Fresco.initialize(this, imagePipelineConfig);
    //        ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this)
    //                .setProgressiveJpegConfig(new SimpleProgressiveJpegConfig())//out of memory if Iuse this
    //                .setResizeAndRotateEnabledForNetwork(true) //out of memory if  use this
    //                .build();
        }
    

    ImageViewer:

                LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                View closeView = layoutInflater.inflate(R.layout.item_photo_gallery, null);
                ImageView ivClose = (ImageView)  closeView.findViewById(R.id.ivClose);
                final ImageViewer viewer = new ImageViewer.Builder(getContext(), photos)
                        .setOverlayView(closeView)
                        .setStartPosition(position)
    //                    .setImageMarginPx(10)
                        .hideStatusBar(false)
                        .build();
                viewer.show();
                ivClose.setOnClickListener(view1 -> viewer.onDismiss());
            }
    
    
    opened by NoNews 6
  • Installation not working

    Installation not working

    I have installed FrescoImageViewer with gradle compile 'com.github.stfalcon:frescoimageviewer:0.5.0', sync the project but class ImageViewer does not exist... Do I have miss something?

    opened by RedFish 4
  •  You need to use a Theme.AppCompat theme (or descendant) with this activity

    You need to use a Theme.AppCompat theme (or descendant) with this activity

    -04 18:26:01.438 5970-5970/com.belisip.belisipstore E/AndroidRuntime: FATAL EXCEPTION: main Process: com.belisip.belisipstore, PID: 5970 java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

    how to solve this ??

    question 
    opened by sondangpangaribuan 4
  • java.lang.NullPointerException: SimpleDraweeView was not initialized!

    java.lang.NullPointerException: SimpleDraweeView was not initialized!

    Hi,I just copy your source code into my project and did not modify any logical code.

    in fragment :

                    new ImageViewer.Builder(activity, activity.imageUrls)
                            .setStartPosition(0)
                            .setImageMargin(activity, R.dimen.image_margin)
                            .setOnDismissListener(activity.getDisissListener())
                            .setImageChangeListener(activity.getImageChangeListener())
                            .setCustomDraweeHierarchyBuilder(activity.getHierarchyBuilder())
                            .setOverlayView(activity.overlayView)
                            .show(); // Error in here.
    

    E/AndroidRuntime: FATAL EXCEPTION: main java.lang.NullPointerException: SimpleDraweeView was not initialized! at com.facebook.common.internal.Preconditions.checkNotNull(Preconditions.java:226) at com.facebook.drawee.view.SimpleDraweeView.init(SimpleDraweeView.java:81) at com.facebook.drawee.view.SimpleDraweeView.(SimpleDraweeView.java:58) at com.frescoimageviewer.drawee.ZoomableDraweeView.(ZoomableDraweeView.java:31) at com.frescoimageviewer.ImageViewerAdapter.getDrawee(ImageViewerAdapter.java:104) at com.frescoimageviewer.ImageViewerAdapter.generateDrawees(ImageViewerAdapter.java:99) at com.frescoimageviewer.ImageViewerAdapter.(ImageViewerAdapter.java:52) at com.frescoimageviewer.ImageViewerView.setUrls(ImageViewerView.java:59) at com.frescoimageviewer.ImageViewer.createDialog(ImageViewer.java:49) at com.frescoimageviewer.ImageViewer.(ImageViewer.java:32) at com.frescoimageviewer.ImageViewer$Builder.build(ImageViewer.java:257) at com.frescoimageviewer.ImageViewer$Builder.show(ImageViewer.java:265) at com.kgv.cookbook.fragment.recipedetail.FirstFragment.onClick(FirstFragment.java:73)

    opened by we3rdo 4
  • can not  scroll to another when image is scaled

    can not scroll to another when image is scaled

    Hi thank for your repository, neither swipe to dimiss nor scroll to another image when image is scaled, I have to reset scale first, i think that is redundant. so how to change sorry for my English.

    opened by sumaro 3
  • Doesn't show image in release version

    Doesn't show image in release version

    The following error occurs when trying to load image in release version: com.stfalcon.frescoimageviewersample does not contain game list

    The strange thing is that it loads ok when run from android studio. Did someone face the same issue?

    opened by AiSa639 2
  • Images are not loading after pulishing to play market

    Images are not loading after pulishing to play market

    in debug mode everything is workig clear but after how i uploaded it to playmarket frescoImageViewer not loading image, its just keeping black screen (background).

    opened by Kratos1013 2
  • "You must call removeView() on the child's parent first" error.

    Hi, while I am adding Image.OnImageChangeListener, I get "The specified child already has a parent. You must call removeView() on the child's parent first" error.

    My code is in RecyclerViewAdapter. First I click the image, image opens as expected. When I touch the same image again, it throws the error. I couldn't find out where I put the "removeView()". Withoutout getImageChangeListener there is no error.

           pageImage.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //fullScreen();
                    new ImageViewer.Builder<>(mContext, myFeedPages)
                            .setStartPosition(position)
                            .setImageChangeListener(getImageChangeListener())
                            .setOverlayView(overlayView)
                            .setFormatter(new ImageViewer.Formatter<Page>() {
                                @Override
                                public String format(Page page) {
                                    return page.getPage_image();
                                }
                            }).show();           
                  }
            });
        }
        private ImageViewer.OnImageChangeListener getImageChangeListener() {
            return new ImageViewer.OnImageChangeListener() {
                @Override
                public void onImageChange(int position) {
                    Page image = myFeedPages.get(position);                   
                    overlayView.setShareText(image.getPage_image());
                    overlayView.setDescription(image.getDescription());                  
                }
            };
        }
    }
    
    opened by criterian 2
  •   java.lang.NoClassDefFoundError com.stfalcon.frescoimageviewer.drawee.ZoomableDraweeView

    java.lang.NoClassDefFoundError com.stfalcon.frescoimageviewer.drawee.ZoomableDraweeView

    Im having this error when trying to build the imageviewer.

    btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String[] arr = new String[5]; arr[0] = "https://c.tadst.com/gfx/750w/doomsday-rule.jpg"; arr[1] = "https://upload.wikimedia.org/wikipedia/commons/2/2a/Keyboard-anykey.jpg"; arr[2] = "https://lh4.googleusercontent.com/YhW2CPU18gJHfmC-e_gaGgs5rPFEld__gXbA-p-CsxK4FcM8qgXjMNVJfATKkKV7UKEdp2497g=s640-h400-e365"; arr[3] = "https://ichef.bbci.co.uk/images/ic/480x270/p01lc1n2.jpg"; arr[4] = "http://static1.businessinsider.com/image/51817e9e6bb3f7601c000016/17-year-cicadas-will-overrun-the-east-coast-any-day-now.jpg"; new ImageViewer.Builder(MainActivity.this, arr) .setStartPosition(1) .show(); } });

    opened by devious33 2
  • Incorrect isScaled due to rounding error

    Incorrect isScaled due to rounding error

    Steps to reproduce:

    1. Zoom the image
    2. Tap back to reset zoom to 1.0
    3. Tap back again has no response
    4. Tap back again to actually go back

    What is expected:

    1. Zoom the image
    2. Tap back to reset zoom to 1.0
    3. Tap back again to go back

    Cause: The zoom factor comparison, isScaled = drawee.getScale() > 1.0f, is broken due to rounding error. On the devices that I've tested, drawee.getScale() can be as large as 1.025 after calling ImageViewHolder.resetScale(). https://github.com/stfalcon-studio/FrescoImageViewer/commit/809b1d2ece90b955cb8d12343c1ca0d5449e744d#diff-e96d3637344c046617a02de7e50fd319R117

    Solution: Use proper float number comparison logic. E.g. isScaled = Math.abs(drawee.getScale() - 1.0f) > MIN_SCALE_DELTA.

    opened by ayltai 2
  • Placeholder customisation

    Placeholder customisation

    The library is really good but I was wondering if this is possible to specify a custom drawable as a placeholder ? Or even a loading spinner animation ?

    opened by r4phab 2
  • set overlay view position

    set overlay view position

    ı am implement close button but, when ı set custom view to .setOverlayView(overlayView), button is in top left position. I wan to set position in top right position. How can ı do to implement ?

    opened by kayduemre 0
  • FLAG_SECURE is not working [Android 10]

    FLAG_SECURE is not working [Android 10]

    Tested on Android 10.

    Setting below Flag with this library wont work getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);

    The user still allowed to take a screenshot or record a video, when the image is opened.

    PS below Android 8... Secure Flag works with this library

    opened by AniketKonnections 0
  • R$color.class

    R$color.class

    My build failed with error: ..\app\build\intermediates\transforms\Blade\debug\0\com\stfalcon\frescoimageviewer\R$color.class (Системе не удается найти указанный путь)

    opened by RamazanGadzhikadiev 0
  • When user tap on image multiple times with very short time span, i'm using onClickListener with debounce though but still this

    When user tap on image multiple times with very short time span, i'm using onClickListener with debounce though but still this "lateinit property transitionImageAnimator has not been initialized" is happening

    kotlin.UninitializedPropertyAccessException: lateinit property transitionImageAnimator has not been initialized at com.stfalcon.imageviewer.viewer.view.ImageViewerView.dispatchTouchEvent(ImageViewerView.kt:155) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3041) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2671) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3041) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2671) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3041) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2671) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3041) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2671) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3041) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2671) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3041) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2671) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3041) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2671) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3041) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2671) at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:565) at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1929) at android.app.Dialog.dispatchTouchEvent(Dialog.java:1061) at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69) at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:514) at android.view.View.dispatchPointerEvent(View.java:12873) at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5771) at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5535) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4983) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5036) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5002) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5157) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5010) at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5214) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4983) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5036) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5002) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5010) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4983) at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:7803) at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:7768) at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7726) at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8007) at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:202) at android.os.MessageQueue.nativePollOnce(Native Method) at android.os.MessageQueue.next(MessageQueue.java:386) at android.os.Looper.loop(Looper.java:175) at android.app.ActivityThread.main(ActivityThread.java:7625) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)

    opened by SubhankarCodeGeek 0
  • Fresco Slider

    Fresco Slider

    Hello, your library is good ... but i need different thing .. instead of array of strings .. i want to pass images from drawable . can it be possible?

    opened by UmairAhmed420 0
Owner
Stfalcon LLC
We specialize in the development of large and medium-sized projects, mobile and web applications, portals with a complex and rich functionality.
Stfalcon LLC
Tutorial Double Tap Pinch to Zoom with kotlin

Double-Tap-Pinch-Zoom Tutorial Double Tap Pinch to Zoom Tutorial Build with Andr

Azhar Rivaldi 6 Apr 13, 2022
PinchToZoom - Pinch to zoom used within list like Instagram

Pinch To Zoom ?? Description Pinch to Zoom with Pan Gestures like Instagram ?? Motivation and Context Big Thanks ???? to the guy and his amazing repo

Vivek Sharma 12 Apr 12, 2022
Slider-Gallery-Zoom: image slider for android supporting indicator and auto scroll with clicking on image

image slider supporting indicator and auto scroll with clicking on image to open full screen image slider swipe and pinch zoom gestures like gallery,just pass your images and the position of the current image.

Mahmoud Elian 3 May 28, 2022
Image Picker with Customizable UI for Android, Pick an image from Gallery

Image Picker A Image Picker Library for Android (Supports Android 12) with fully

null 2 May 29, 2022
ImageView and FrameLayout with gestures control and position animation

GestureViews ImageView and FrameLayout with gestures control and position animation. Main goal of this library is to make images viewing process as sm

Alex Vasilkov 2.3k Dec 30, 2022
Implementation of ImageView for Android that supports zooming, by various touch gestures.

PhotoView PhotoView aims to help produce an easily usable implementation of a zooming Android ImageView. [ Dependency Add this in your root build.grad

Baseflow 18.4k Dec 30, 2022
Implementation of ImageView for Android that supports zooming, by various touch gestures.

PhotoView PhotoView aims to help produce an easily usable implementation of a zooming Android ImageView. [ Dependency Add this in your root build.grad

Baseflow 18.4k Dec 27, 2022
An awesome photo album viewer.

An awesome photo album viewer.

null 15 Jun 13, 2022
Mobile development Exercise Simple photo viewer

Mobile development Simple Photo viewer Exercise A simple photo viewer based on Udacitys example app "dice roller"." Mobile development Exercise Simple

null 0 Oct 16, 2021
Custom ImageView for moving image around the screen (Android)

MovingImageView Create a custom ImageView for moving image around the screen. Usage To use MovingImageView, add the module into your project and start

Albert Grobas 819 Nov 18, 2022
DMIV aims to provide a flexible and customizable instrument for automated images moving on display. It provides scroll, gyroscope or time based moving. But you can create your own evaluator.

DexMovingImageView DMIV aims to provide a flexible and customizable instrument for automated images moving on display. It provides scroll, gyroscope o

Diego Grancini 310 Feb 7, 2022
Android library to generate image avatar from the first letter of a username. Letter avatar like Gmail Android best practice

AvatarImageGenerator Generate first letter avatar Image like gmail's contact avatar. It generates an drawable that can be be set to an ImageView. Inst

Korir Amos 61 Sep 25, 2022
Android library written in kotlin that add a noise effect to image.

NoiseView With NoiseView you can easily add a noise effect to your image. See demo on YouTube Setup The library is pushed to jCenter() as an AAR, so y

Przemek 46 Sep 8, 2022
This is a library for make auto slide image in android

Auto Image Slider Screenshot Image Slider Default Image Slider With Custom Adapter Usage Add ImageSlider to your layout

Afdhal_FA 17 Dec 1, 2022
Android Library for cropping an image at ease.

Cropper - Android Image Cropper Android Image Cropper Powerful (Zoom, Rotation, Multi-Source); Customizable (Shape, Limits, Style); Optimized (Async,

Akshat Tiwari 24 Aug 24, 2022
A library for Android provides blurred drop shadows to ImageView similar to iOS image backdrop shadows

A library for Android provides blurred drop shadows to ImageView similar to iOS image backdrop shadows.Provides fast canvas draw as no renderscript needed .The similar shadow blurred effects can also be seen in iOS Music App.

Vivek Verma 163 Dec 31, 2022
Android widget for cropping and rotating an image.

Cropper The Cropper is an image cropping tool. It provides a way to set an image in XML and programmatically, and displays a resizable crop window on

Edmodo 2.9k Nov 14, 2022
Add curve at bottom of image views and relative layouts.

Crescento Android library that adds a curve at the below of image views and relative layouts. CrescentoImageView and CrescentoContainer are the image

Shivam Satija 1.3k Nov 18, 2022