13

View That I Wanted

I want To Create Image Thumb Like Above.. For This I Created XML Below

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">


      <View
            android:id="@+id/view1"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:layout_marginTop="10dp"    
            android:background="@drawable/images1">
        </View>
        <View
            android:id="@+id/view2"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:layout_marginTop="20dp"
            android:layout_marginLeft="10dp"
            android:background="@drawable/images1">
        </View>
        <View
            android:id="@+id/view3"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:layout_marginTop="30dp"
            android:layout_marginLeft="20dp"
            android:background="@drawable/images1">
        </View>

</RelativeLayout>

But This Which I Created Is Manually Added In XML. And May Be It Will React Different in Different device Type. Is There Any Other Way To Create This Type Of View..

Any Help Accepted.

Thank You.

AskNilesh
  • 67,701
  • 16
  • 123
  • 163
Learning Always
  • 1,563
  • 4
  • 29
  • 49

6 Answers6

12

Your idea is fine. You are using dp as size units so Views will look similarly on different devices. The only thing I can propose as an improvement - move all this stuff to separate View class:

class ThumbView extends RelativeLayout {
    private ImageView vLayer1;
    private ImageView vLayer2;
    private ImageView vLayer3;

    public ThumbView(Context context, String pathToFile) {
        super(context);
        LayoutInflater inflater = (LayoutInflater) getContext()
          .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View view = inflater.inflate(R.layout.view_thumb, this, true);
        vLayer1 = view.findViewById(R.id.view1);
        vLayer2 = view.findViewById(R.id.view2);
        vLayer3 = view.findViewById(R.id.view3);

        Drawable drawable = Drawable.createFromPath(pathToFile);

        vLayer1.setImageDrawable(drawable);
        vLayer2.setImageDrawable(drawable);
        vLayer3.setImageDrawable(drawable);
    }
}

I assume that you are going to use files from gallery for the thumbs so added path to file to constructor. So it will be easier to create these views from code.

Another approach that you can use for this purpose is drawing of Bitmaps directly on Canvas. This way can provide some performance advantages if you suppose to create a great amount of such views (to show them for example in List/Grid). Please follow this Guide for more details.

DmitryArc
  • 4,757
  • 2
  • 37
  • 42
  • yes, creating different class is good Idea.. But My Xml Is From Adapter Class Which is Shown In List View.. Is This Valid To Create That Kind Of Class For Adapter (Sorry For Incomplete Info. in Question) – Learning Always Dec 21 '17 at 10:48
  • and yes the thumb image was from gallery or camera – Learning Always Dec 21 '17 at 10:55
  • 2
    in Adapter you can do without any additional class. In getView() you already have something like view = yourInflater.inflate(...). So you have just to put images to the layers as described above. – DmitryArc Dec 21 '17 at 11:00
6

You can use this custom view.

LayeredImageView.java

public class LayeredImageView extends RelativeLayout {
    private final int offset = 50;
    private int offsetMargin = offset;
    private int count = 0;
    private int imageHeight = 600;
    private int imageWidth = 600;
    private Context context;
    private Paint paint = new Paint();

    public LayeredImageView(Context context) {
        super(context);
        this.context = context;
        init();
    }

    private void init() {
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(3);
        this.setWillNotDraw(false);
        paint.setColor(Color.WHITE);
    }

    public LayeredImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
    }

    public LayeredImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init();
    }

    public void addImage(int res) {
        count++;
        ImageView imageView = new ImageView(context);
        imageView.setImageDrawable(ContextCompat.getDrawable(context, res));
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
                imageWidth,
                imageHeight);
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        params.setMargins(offsetMargin, offsetMargin, 0, 0);
        imageView.setLayoutParams(params);
        this.addView(imageView);
        this.invalidate();
        offsetMargin += offset;
    }

    public void setImageHeight(int imageHeight) {
        this.imageHeight = imageHeight;
    }

    public void setImageWidth(int imageWidth) {
        this.imageWidth = imageWidth;
    }

    @Override
    public void onDrawForeground(Canvas canvas) {
        for (int o = offset, i = 0; i < count; o += offset, i++) {
            canvas.drawRect(o, o, imageWidth + o, imageHeight + o, paint);
        }
        super.onDrawForeground(canvas);
    }
}

The view contains some hardcoded values which you can change depending on your needs.

Then in your activity or fragment inflate the layout and add the images dynamically

LayeredImageView view = (LayeredImageView) findViewById(R.id.view);
view.addImage(R.drawable.img_1);
view.addImage(R.drawable.img_2);
view.addImage(R.drawable.img_3);

DEMO

enter image description here

Gautam Chibde
  • 1,167
  • 3
  • 14
  • 27
2

For overlapping views, FrameLayout is the exact container you should use as it is built for this purpose. FrameLayout stacks child views one on the other with the most recently added one on the top. The z-index depends on the order of the child views. In the layout below, view3 will be above view2 and view2 will be above view1.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/view1"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="10dp"
        android:background="@drawable/images1">
    </View>
    <View
        android:id="@+id/view2"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="20dp"
        android:layout_marginLeft="10dp"
        android:background="@drawable/images1">
    </View>
    <View
        android:id="@+id/view3"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="30dp"
        android:layout_marginLeft="20dp"
        android:background="@drawable/images1">
    </View>

</FrameLayout>
1

Just copy and pase below code FrameLayout is specially designed for this purpose here below is Root Layout is FrameLayout then

Imageview one after Another

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
    android:id="@+id/imageview1"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:layout_marginTop="10dp"
    android:background="@color/colorPrimary">
</ImageView>
<ImageView
    android:id="@+id/imageview2"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:layout_marginTop="20dp"
    android:layout_marginLeft="10dp"
    android:background="@color/colorPrimaryDark">
</ImageView>
<ImageView
    android:id="@+id/imageview3"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:layout_marginTop="30dp"
    android:layout_marginLeft="20dp"
    android:background="@color/colorAccent">
</ImageView> </FrameLayout>

try this and let me know please

Sanju Baghla
  • 170
  • 1
  • 13
0

Use a frame layout and use marginLeft and marginTop in increasing order for each image view. You can use a library to provide margin dimensions in order to get a responsive output.

https://github.com/intuit/sdp

You can even add image views with different margins to frame layout programatically using a loop. This will allow you to add any number of image views according to your input.

-1

use this code ...

View view = inflater.inflate(R.layout.view_thumb, this, true);
            viewLayer1 = view.findViewById(R.id.view1);
            viewLayer2 = view.findViewById(R.id.view2);
            viewLayer3 = view.findViewById(R.id.view3);
    Drawable drawable = Drawable.createFromPath(pathToFile);

            viewLayer1.setImageDrawable("@drawable/images1");
            viewLayer2.setImageDrawable("@drawable/images1");
            viewLayer3.setImageDrawable("@drawable/images1");

your problem must be solved