8

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>
jason
  • 6,962
  • 36
  • 117
  • 198

3 Answers3

5

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);
}
Zaartha
  • 1,106
  • 9
  • 25
4

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!

Community
  • 1
  • 1
Erik Minarini
  • 4,795
  • 15
  • 19
  • Thanks, I prefer using gestures instead of animation. Because they are more realistic. – jason Jun 28 '16 at 07:30
  • yeah, ok! So, maybe you can try to draw your view on a canvas and then you can use the scale() method of the Canvas class to resize it during your gesture. Here there is an example https://developer.android.com/training/gestures/scale.html – Erik Minarini Jun 28 '16 at 08:04
3

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.

yan yankelevich
  • 885
  • 11
  • 25
  • I took the code from somewhere, it was working with imageviews but doesn't work with mapview and a chart. So I don't know the code much. – jason Jun 28 '16 at 10:36
  • Could you add pictures of what happens and what you want to happen please ? It's hard to me to understand what you want to achieve. From what i understand you want to scale up and down your Chart and your map view when you image view "moves". That's the part i don't get. How is your imageView supposed to move ? Up and down ? Left and right ? In any direction ? Why do you want to resize your Chart and map instead of just pushing them out of screen ? – yan yankelevich Jun 28 '16 at 11:21
  • Okay i think i got it ! If i got it right you want to drag up and down your red line, and this way make your Chart or your Mapview fill the avaible space below and above this line depending on its position. Am i right ? – yan yankelevich Jun 28 '16 at 11:31
  • Correct, if you drag up chart gets smaller, and map gets bigger at the same rate. – jason Jun 28 '16 at 11:36
  • I don't ensure you the code i just added will work, i have no way to test it now, it doesn't manage your min and max height parameters, maybe it won't work at all, i don't know ^^ – yan yankelevich Jun 28 '16 at 12:28