Home » Android » android – Smooth resizing a chart and a mapview

android – Smooth resizing a chart and a mapview

Posted by: admin June 15, 2020 Leave a comment

Questions:

I have a pie chart and mapview on the screen. Between chart and mapview, there is a small imageview. When imageview moves, chart and mapview are supposed to have grow and shrink. It works, but when I move imageview, app is shaking. I want their sizes to change smoothly. I think it is due to pie chart. How can I fix this? Thanks.
Here is my Java code :

final LinearLayout aboveLinear = (LinearLayout) findViewById(R.id.aboveLinear);
        final LinearLayout belowLinear = (LinearLayout) findViewById(R.id.belowLinear);

        final ImageView imageView2 = (ImageView) findViewById(R.id.imageView2);


        detector = new GestureDetectorCompat(this, new GestureDetector.SimpleOnGestureListener() {

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                if ( aboveLinear == null || belowLinear == null ) {
                    return true;
                }
                distanceY*=-1;
                int height = aboveLinear.getHeight ( ) + mapview.getHeight ( );
                ViewGroup.LayoutParams layoutParams = aboveLinear.getLayoutParams ( );
                if ( ( int ) distanceY + layoutParams.height < minH )
                    layoutParams.height = minH;
                else if ( ( int ) distanceY + layoutParams.height > height - minH )
                    layoutParams.height = height - minH;
                else
                    layoutParams.height = ( int ) distanceY + layoutParams.height;

                ViewGroup.LayoutParams layoutParams2 = belowLinear.getLayoutParams ( );
                layoutParams2.height = height - layoutParams.height;

                aboveLinear.setLayoutParams ( layoutParams );
                belowLinear.setLayoutParams ( layoutParams2 );

                return true;
            }
        });

        imageView2.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(final View view, final MotionEvent motionEvent) {
                return detector.onTouchEvent(motionEvent);
            }
        });


        mapview = (MapView) findViewById(R.id.mapview);
        mapview.onCreate(savedInstanceState);

        chart1 = (PieChart) findViewById(R.id.chart1);
        chart1.setUsePercentValues(true);
        chart1.setDescription("");
        chart1.setExtraOffsets(5, 10, 5, 5);

        chart1.setDragDecelerationFrictionCoef(0.95f);

Here is my xml code :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    xmlns:mapbox="http://schemas.android.com/apk/res-auto"
    android:id="@+id/root">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:id="@+id/aboveLinear">

        <com.github.mikephil.charting.charts.PieChart
            android:id="@+id/chart1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentTop="true"
            android:scaleType="fitXY"/>

   </LinearLayout>

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="match_parent"
        android:layout_height="25dp"
        android:layout_alignParentTop="true"
        android:clickable="true"
        android:scaleType="fitXY"
        android:src="@drawable/red"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:id="@+id/belowLinear">

        <com.mapbox.mapboxsdk.maps.MapView
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:id="@+id/mapview"
            android:layout_width="fill_parent"
            mapbox:access_token="@string/accessToken"
            mapbox:style_url="@string/style_mapbox_streets"
            mapbox:center_latitude="41.885"
            mapbox:center_longitude="-87.679"
            mapbox:zoom="12"
            mapbox:tilt="20"/>
    </LinearLayout>

   </LinearLayout>
How to&Answers:

You dont need animation to do this.
Dont calculate height every time.
This solution will help you

 private MapView mapview;
PieChart chart1;
GestureDetectorCompat detector;
int minH = 100;
int height = 0;
private LinearLayout aboveLinear;
private LinearLayout belowLinear;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mappie);

    aboveLinear = (LinearLayout) findViewById(R.id.aboveLinear);
    belowLinear = (LinearLayout) findViewById(R.id.belowLinear);

    final ImageView imageView2 = (ImageView) findViewById(R.id.imageView2);


    detector = new GestureDetectorCompat(this, new GestureDetector.SimpleOnGestureListener() {

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            if ( aboveLinear == null || belowLinear == null ) {
                return true;
            }
            if(distanceY > 90){
                distanceY = 90;
            }
            else if(distanceY < -90){
                distanceY = -90;
            }
            distanceY*=-1;
            if(height == 0){
                height = aboveLinear.getMeasuredHeight()+belowLinear.getMeasuredHeight();// calculate only once
            }
            Log.wtf("Mapie","Height :"+height);
            int toHeightAL, toHeightBl;
            ViewGroup.LayoutParams layoutParams = aboveLinear.getLayoutParams ( );

            if(layoutParams.height == 0){
                layoutParams.height = height/2; // params.height returns 0 before setting the value for it
            }

            if ( ( int ) distanceY + layoutParams.height < minH )
                toHeightAL = minH;
            else if ( ( int ) distanceY + layoutParams.height > height - minH )
                toHeightAL = height - minH ;
            else
                toHeightAL = ( int ) distanceY + layoutParams.height;

            ViewGroup.LayoutParams layoutParams2 = belowLinear.getLayoutParams ();
            toHeightBl = height - layoutParams.height;

            layoutParams.height = toHeightAL;
            layoutParams2.height = toHeightBl;
            aboveLinear.setLayoutParams ( layoutParams );
            belowLinear.setLayoutParams ( layoutParams2 );

            return true;
        }
    });

    imageView2.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(final View view, final MotionEvent motionEvent) {

            return detector.onTouchEvent(motionEvent);
        }
    });


    mapview = (MapView) findViewById(R.id.mapview);
    mapview.onCreate(savedInstanceState);

    chart1 = (PieChart) findViewById(R.id.chart1);
    chart1.setUsePercentValues(true);
    chart1.setDescription("");
    chart1.setExtraOffsets(5, 10, 5, 5);

    chart1.setDragDecelerationFrictionCoef(0.95f);
}

Answer:

You can try to use an animation for resizing this view.
Instead to set height and width equals to a value, maybe you have to animate from starting height/width to the height/width you want to use.

Check here https://stackoverflow.com/a/8162779/6093353. This user wrote a very simple custom animation to resize a view, but you can write the animation you want your own.

Let me know if this helps you!

Answer:

Try to replace the OnScroll function with this (i didn’t tried this, nor typed it in a java IDE so maybe i’m not accessing the properties the right way as i’m more used to C#) :

public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
    {
        if (aboveLinear == null || belowLinear == null)
        {
            return true;
        }
        int currentY = e1.getY();
        float ratio = abovelinear.getHeight() / (aboveLinear.Bottom - currentY);
        aboveLinear.SetScaleY( aboveLinear.GetScaleY()- ratio);
        belowLinear.SetScaleY(belowLinear.GetScaleY() +ratio); 

        return true;
    }
});

This should work only one way (down to top), but with some time you should be able to obtain what you are looking for.