Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Smooth resizing a chart and a mapview

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>
like image 929
jason Avatar asked Jun 20 '16 07:06

jason


3 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);
}
like image 121
Zaartha Avatar answered Sep 23 '22 16:09

Zaartha


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!

like image 30
Erik Minarini Avatar answered Sep 23 '22 16:09

Erik Minarini


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.

like image 22
yan yankelevich Avatar answered Sep 25 '22 16:09

yan yankelevich