3

I am creating layout dynamically by using left and top values of api. The api data is is like below:-

{
"isSuccess": true,
"data": [{
        "left": "159",
        "top": "17",
        "seat_name": "Staff"
    },
    {
        "left": "159",
        "top": "65",
        "seat_name": "Staff"
    },
    {
        "left": "238",
        "top": "15",
        "seat_name": "3"
    },
    {
        "left": "239",
        "top": "66",
        "seat_name": "4"
    },
    {
        "left": "313",
        "top": "13",
        "seat_name": "5"
    },
    {
        "left": "314",
        "top": "67",
        "seat_name": "6"
    },
    {
        "left": "241",
        "top": "223",
        "seat_name": "7"
    },
    {
        "left": "239",
        "top": "160",
        "seat_name": "8"
    },
    {
        "left": "314",
        "top": "159",
        "seat_name": "9"
    },
    {
        "left": "315",
        "top": "223",
        "seat_name": "10"
    },
    {
        "left": "366",
        "top": "223",
        "seat_name": "11"
    },
    {
        "left": "364",
        "top": "160",
        "seat_name": "12"
    },
    {
        "left": "374",
        "top": "71",
        "seat_name": "13"
    },
    {
        "left": "371",
        "top": "12",
        "seat_name": "14"
    },
    {
        "left": "430",
        "top": "12",
        "seat_name": "15"
    },
    {
        "left": "432",
        "top": "68",
        "seat_name": "16"
    },
    {
        "left": "428",
        "top": "158",
        "seat_name": "17"
    },
    {
        "left": "431",
        "top": "223",
        "seat_name": "18"
    },
    {
        "left": "493",
        "top": "12",
        "seat_name": "19"
    },
    {
        "left": "492",
        "top": "64",
        "seat_name": "20"
    },
    {
        "left": "491",
        "top": "158",
        "seat_name": "21"
    },
    {
        "left": "486",
        "top": "222",
        "seat_name": "22"
    },
    {
        "left": "555",
        "top": "14",
        "seat_name": "23"
    },
    {
        "left": "553",
        "top": "65",
        "seat_name": "24"
    },
    {
        "left": "553",
        "top": "160",
        "seat_name": "25"
    },
    {
        "left": "553",
        "top": "220",
        "seat_name": "26"
    },
    {
        "left": "616",
        "top": "16",
        "seat_name": "27"
    },
    {
        "left": "618",
        "top": "65",
        "seat_name": "28"
    },
    {
        "left": "620",
        "top": "117",
        "seat_name": "29"
    },
    {
        "left": "618",
        "top": "166",
        "seat_name": "30"
    },
    {
        "left": "619",
        "top": "216",
        "seat_name": "31"
    }
]}

And the code I have written to create layout is:

    private void createLayout() {
    ScrollView objScrollView = new ScrollView(this);
    ViewGroup.LayoutParams objLayoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
    objScrollView.setLayoutParams(objLayoutParams);
    RelativeLayout objParentLayout = new RelativeLayout(this);
    RelativeLayout.LayoutParams objParentParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);

    int intId = 100;
    int intLeft = 0;
    for (int i = 0; i < arrobjSeats.size(); i++) {
        Seat objSeat = arrobjSeats.get(i);

        RelativeLayout objItemLayout = new RelativeLayout(this);
        RelativeLayout.LayoutParams objItemParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
        objItemParams.setMargins(objSeat.getIntTop() + 30, objSeat.getIntLeft() - 110, 0, 10);
        intLeft = objSeat.getIntTop();

        ImageView imgSeat = new ImageView(this);
        imgSeat.setImageResource(R.drawable.ic_airline_seat_recline_normal_black_24dp);
        imgSeat.setColorFilter(Color.parseColor(objSeat.getStrSeatColor()), android.graphics.PorterDuff.Mode.SRC_IN);
        imgSeat.setPadding(5, 5, 10, 25);
        imgSeat.setId(intId++);
        RelativeLayout.LayoutParams objImageParams = new RelativeLayout.LayoutParams(120, 80);
        objImageParams.addRule(RelativeLayout.CENTER_HORIZONTAL);

        TextView txtSeatName = new TextView(this);
        RelativeLayout.LayoutParams objTextParams = new RelativeLayout.LayoutParams(120, RelativeLayout.LayoutParams.WRAP_CONTENT);
        objTextParams.addRule(RelativeLayout.ALIGN_BOTTOM, imgSeat.getId());
        txtSeatName.setPadding(5, 10, 5, 5);
        txtSeatName.setTextColor(Color.parseColor(objSeat.getStrSeatColor()));
        txtSeatName.setText(objSeat.getStrSeatName());
        txtSeatName.setGravity(Gravity.CENTER);
        txtSeatName.setTextSize(16);

        objItemLayout.setTag(i);

        objItemLayout.addView(imgSeat, objImageParams);
        objItemLayout.addView(txtSeatName, objTextParams);

        objItemLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int intPosition = (int) v.getTag();
                Seat objSeat = arrobjSeats.get(intPosition);
                Toast.makeText(SeatActivity.this, "Seat=>" + objSeat.getIntSeatId() + "=>" + objSeat.getStrSeatName(), Toast.LENGTH_SHORT).show();
            }
        });
        objParentLayout.setBackgroundColor(Color.CYAN);
        objParentLayout.addView(objItemLayout, objItemParams);
        System.out.println("Final Color=>" + objSeat.getStrSeatColor());
    }
    objScrollView.addView(objParentLayout, objParentParams);
    relativeLayout.addView(objScrollView);
}

So using above code, I am getting output like below (almost perfect). Just having issue with spacing between each item:

enter image description here

Note: I have already implemented this api in React Native by applying absolute position parameter on view. It's showing UI perfectly on many Android devices, I have tested it.

So my problems are:

  1. Why layout not taking full device width and height, after setting layout parmas to MATCH_PARENT/FILL_PARENT? (Also tried with fixed layout values like 120dp width and height given.)
  2. When I tried with setting background to each item, can see each item gets overlapped with its corresponding item. Don't know WHY?

Have I done anything wrong in the above code?

halfer
  • 19,824
  • 17
  • 99
  • 186
Anil Ravsaheb Ghodake
  • 1,587
  • 2
  • 27
  • 45
  • 1
    Your `objItemLayout` is `wrap_content` cause you did not set any `LayoutParams` to it . Apart from that i suggest use a layout xml and Use `LayoutInflater` to inflate view at runtime . Arranging views at runtime will result in lots of lines of codes and can be too tricky in some scenario. – ADM Apr 27 '18 at 05:42
  • @SaurabhBhandari, I don't want to align my created layout to the center of parent. You can see in image its little bit congested.So I want to make it spacious – Anil Ravsaheb Ghodake Apr 27 '18 at 05:43
  • try this like objScrollView.setFillViewport(true); – GParekar Apr 27 '18 at 05:51
  • @ADM, I have tries to set static height width as well instead of WRAP_CONTENT ,but its get overlapped. Also tried with inflating XML layout,but not worked gets same output. – Anil Ravsaheb Ghodake Apr 27 '18 at 05:52
  • @GParekar, Not working. – Anil Ravsaheb Ghodake Apr 27 '18 at 05:54
  • Trying moving objScrollView.addView(objParentLayout, objParentParams); relativeLayout.addView(objScrollView); lines above for loop. And is there any particular reason to use FILL_PARENT, use MATCH_PARENT for both dimensions – Manish Apr 27 '18 at 06:35
  • @Manish, There is no reason ot use MATCH_PARENT or FILL_PARENT. I just want to make sure that, the created layout should take all parent space and arrange its item separately, not overlapped. – Anil Ravsaheb Ghodake Apr 27 '18 at 07:04
  • Have you tried moving it up and setting match_parent for both – Manish Apr 27 '18 at 07:24
  • @Manish, Yes I have tried, but gets same output – Anil Ravsaheb Ghodake Apr 27 '18 at 07:31
  • Have you exact 31 seats? – Rumit Patel Apr 27 '18 at 09:41
  • @RumitPatel, No it can varies to any value. – Anil Ravsaheb Ghodake Apr 27 '18 at 09:55
  • create a single item then after try i hope it will help you. – Hardik Vasani Apr 28 '18 at 06:07
  • @HardikVasani, can't understand what u want to say. Can u please elaborate your point once? – Anil Ravsaheb Ghodake Apr 28 '18 at 06:34
  • @AnilGhodake according to documentation of recyclerview you can create single Item layout and fill data as required. – Hardik Vasani Apr 28 '18 at 06:46
  • @HardikVasani,Thanks, I will try with recyclerview once. If you have any example/demo code of it please share it here. – Anil Ravsaheb Ghodake Apr 28 '18 at 06:49
  • @AnilGhodake u can get object Imagview and Textview using LayoutInflater – Hardik Vasani Apr 28 '18 at 07:24
  • How is `relativeLayout` defined? It seems to be your top-level view, but I don't see where it is defined. Also, can you supply your `Seat` class? – Cheticamp May 11 '18 at 11:53
  • @Cheticamp,You can see in above code **My Parent layout is _Scrollview_ which has main child as relative layout**, and this relative layout having each seat as one relative layout. **_Seat class_** is just a model class which store Seat name,color and position related information – Anil Ravsaheb Ghodake May 14 '18 at 08:43
  • I see that. However, the last line of code is `relativeLayout.addView(objScrollView);`. This adds your scroll view to `relativeLayout`, but I don't see where `relativeLayout` is defined. That is the relative layout I am asking about. It is different from `objParentLayout`. – Cheticamp May 14 '18 at 12:21
  • @Cheticamp, That relative layout referred from layout file, for now it's does not contain anything, I added it because need to display some other information above scrollable seat layout. – Anil Ravsaheb Ghodake May 14 '18 at 12:52
  • @AnilGhodake when you set margins to LayoutParams it works with it as with pixels, so all you do in you code is setting absolute coordinates to your seats in pixels. I think, the best way to place seats for all width is to recalculate positions according to device screen size(or better view sizes,for example in OnMeasure/onLayout methods). – Danylo.Vus May 15 '18 at 09:54
  • @Danylo.Vus, How it would calculate values at runtime, in OnMeasure/OnLayout methods? Is there any example or reference code you have? – Anil Ravsaheb Ghodake May 15 '18 at 10:01
  • 1
    @AnilGhodake you need to get width of objScrollView how to do this look https://stackoverflow.com/questions/2159320/how-to-size-an-android-view-based-on-its-parents-dimensions than find seat with maximum left point after that you can calculate scale coefficient multiply all left and right margins of seats for example objScrollView width is 600 , maximum left point is 250 and width of seat is 100,than your scaleCoef is (600-100)/250 = 2; after thad you can add seats just with objItemParams.setMargins(objSeat.getIntTop() * scaleCoef, objSeat.getIntLeft() - 110, 0, 10); – Danylo.Vus May 15 '18 at 13:53
  • You need to convert number to dp and sp then use the results with these methods (now you are using them as px and that make unwanted result): setPadding() setTextSize() setMargins() Then you should use WRAP_CONTENT or MATCH_PARENT. – MohammadL May 16 '18 at 03:36
  • @Danylo.Vus, Can u please add your comment as answer, So I can accept it as answer.Also how I can divide height equally? – Anil Ravsaheb Ghodake May 16 '18 at 07:41

1 Answers1

2

First of all you need to get sizes of view in which seats will be placed. Easy way - to get display width and height:

Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;

but this will be hard to maintain (you will have no opportunity to move this to other container) Better way - create custom ViewGroup (for example FrameLayout) and override onMeasure/onLayout methods see How to size an Android view based on its parent's dimensions

After you get sizes, you must recalculate positions. First get maximum left and maximum top point. Than calculate scale coefficient. For example if screan width is 600, maximum left point is 250 and width of seat is 100 than scale width coefficient is (600-100)/250 = 2 Than add all your seats using coefficients :

objItemParams.setMargins(objSeat.getIntTop() * scaleCoefWidth, objSeat.getIntLeft() * scaleCoefHeigth, 0, 0);

Note,that if you want to add this to vertical scroll than you need change logic of getting height (for example if number of seat is less than 10,draw them all on screan, if more that 10,than height must be more than screen(or ViewGroup) heigth to allow vertical scroll.

Danylo.Vus
  • 969
  • 9
  • 11