4

I want to make a star shape for my project. and I searched so, now I can make finally star shape by using canvas.

but next what I want is really really difficult to me. It`s so nightmare. I tried and searched but nothing works for me.

what I want is star have to consist of lines with no background color. only line.. across the line..

And then one line is expressed and fade, the next line is created and fade again, then the line is created and then fade again, and I want it to be permanent this action. Until I leave this activity's screen to another.

Juli di
  • 127
  • 1
  • 12

2 Answers2

6

This code is taken from a project I was working on some time back. I think it does what you need.

First of all, I have no idea about how you have created the lines for the star. I just used vector drawables to create the star lines (for more details about how to work with VectorDrawables have a look at this post). I should warn you that I made it in a hurry so it's not going to be pretty

Warning: This post is going to be long

star1.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="48dp"
    android:height="48dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">    
    <path android:pathData="M20,24L12,0"
        android:strokeColor="@color/starColor"
        android:strokeWidth="0.1"/>    
</vector>

star2.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="48dp"
    android:height="48dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">    
    <path android:pathData="M4,24L12,0"
        android:strokeColor="@color/starColor"
        android:strokeWidth="0.1"/>    
</vector>

star3.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="48dp"
    android:height="48dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">    
    <path android:pathData="M0,8L24,8"
        android:strokeColor="@color/starColor"
        android:strokeWidth="0.1"/>    
</vector>

star4.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="48dp"
    android:height="48dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path android:pathData="M4,24L24,8"
        android:strokeColor="@color/starColor"
        android:strokeWidth="0.1"/>
</vector>

star5.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="48dp"
    android:height="48dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path android:pathData="M20,24L0,8"
        android:strokeColor="@color/starColor"
        android:strokeWidth="0.1"/>
</vector>

Ok. Now that you have all the required drawables, let's jump to the Activity XML and create the layout. Just the basic stuff here. I'll be using 5 ImageViews to hold the different star lines (which makes it convenient to animate but could cause performance issues which we'll talk about later on). I'll be using a ConstraintLayout as the root view.

activity_test.xml

<android.support.constraint.ConstraintLayout 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">

    <ImageView
        android:id="@+id/image1"
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:alpha="0"/>

    <ImageView
        android:id="@+id/image2"
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:alpha="0"/>

    <ImageView
        android:id="@+id/image3"
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:alpha="0"/>

    <ImageView
        android:id="@+id/image4"
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:alpha="0"/>

    <ImageView
        android:id="@+id/image5"
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:alpha="0"/>

</android.support.constraint.ConstraintLayout>

As you might have noticed I have not assigned any of the drawables to the ImageView using the android:src property. I'd encourage you to go ahead and try doing that. Meanwhile I am adding the images programmatically.

Above the onCreate method declare the following variables

private ImageView image1, image2, image3, image4, image5;
private Context context;
private int i = 1;
private long duration = 800;
private Handler animHandler;

animHandler is going to be responsible to keep the animation running. I'll be using i to keep track of which ImageView to animate. And as the name suggests, the field duration is going to hold the required duration for the animation.

Here is the rest of the code. I'll be providing comments wherever possible.

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

    // Initialising the imageview. I'm using SDK 26 so I did not
    // require typecasting.
    image1 = findViewById(R.id.image1);
    image2 = findViewById(R.id.image2);
    image3 = findViewById(R.id.image3);
    image4 = findViewById(R.id.image4);
    image5 = findViewById(R.id.image5);

    context = TestActivity.this;

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            setupView(); // This method will initialize all IVs 
                         // and add the vector drawable as bitmap
            animHandler = new Handler();
            startAnim();
        }
    }, 200);

}

setupView

private void setupView() {
    setVectorDrawable(image1, ContextCompat.getDrawable(context,R.drawable.star1));
    setVectorDrawable(image2, ContextCompat.getDrawable(context,R.drawable.star2));
    setVectorDrawable(image3, ContextCompat.getDrawable(context,R.drawable.star3));
    setVectorDrawable(image4, ContextCompat.getDrawable(context,R.drawable.star4));
    setVectorDrawable(image5, ContextCompat.getDrawable(context,R.drawable.star5));
}

setVectorDrawable

private void setVectorDrawable(ImageView imageView, Drawable drawable) {
    Bitmap bitmap = Bitmap.createBitmap(imageView.getWidth(),
            imageView.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);

    imageView.setImageBitmap(bitmap);
}

Over here, I'm creating 5 different bitmaps to hold the 5 lines. This won't be too much of an issue just yet. But for bigger projects (I had to use 69 bitmaps together) having a lot of bitmaps in the memory is probably not a good practice. 5 bitmaps should work just fine.

startAnim

private void startAnim() {
    runnable.run();
}

runnable

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        switch (i) {
            case 1:
                animateStarIn(image1);
                break;
            case 2:
                animateStarIn(image2);
                break;

            case 3:
                animateStarIn(image3);
                break;
            case 4:
                animateStarIn(image4);
                break;

            case 5:
                animateStarIn(image5);
                break;
            case 6:
                animateStartOut(image1);
                break;

            case 7:
                animateStartOut(image2);
                break;
            case 8:
                animateStartOut(image3);
                break;

            case 9:
                animateStartOut(image4);
                break;
            case 10:
                animateStartOut(image5);
                break;
        }
        i++;
        if (i == 11) i = 1;
        animHandler.postDelayed(runnable, duration);
    }
};

private void animateStarIn(ImageView imageView) {
    imageView.animate().alpha(1).setDuration(duration).setInterpolator(new AccelerateInterpolator());
}
private void animateStartOut (ImageView imageView) {
    imageView.animate().alpha(0).setDuration(duration).setInterpolator(new DecelerateInterpolator());
}

To be brief, I am creating a runnable that will animate the different ImageViews differently depending on the value variable i holds.

Let me stress again that I have posted this code from a project that I worked on some time back. Even if it does not meet your requirement directly I'd encourage you to experiment and play around with it for a bit to get it working.

Edit

This animation works by ensuring the runnable repeats. To stop the animation use

animHandler.removeCallbacks(runnable);
Ajil O.
  • 5,192
  • 4
  • 34
  • 59
  • Wow.. So unbelievable. It`s perfect. but you said, "which makes it convenient to animate but could cause performance issues which we'll talk about later on". I'll put this in my app. Will there be a performance issue? Is there anything better to do with optimization than to use it? For example, create and attach a GIF. The functionality is perfect, but lastly, I want to ask about performance issues. – Juli di Sep 26 '17 at 06:41
  • @Julidi If we are talking about 5 `ImageView`s it will not affect the performance as such. Android monitor shows 7MB being used (which is not much). Moreover, in the example, I have used `ImageView` size as `200dp`. If you were to scale it down, to say 75dp the memory usage comes down to 1-2MB. Working with `path` to draw on canvas would be more efficient memory-wise, but more time-consuming. – Ajil O. Sep 26 '17 at 06:58
  • And how to stop it?? – Juli di Oct 25 '17 at 10:04
  • Thx!! do I have to use this kind of singleton pattern or static class? or you think better to make this being general objective? I just thought it`s long code for one activity. – Juli di Oct 25 '17 at 13:42
0

I do not think you will find code for doing exactly what you want, but you can take other code and adapt it.

You can take code that draws a star line by line on a canvas (for example, take it from here: drawing a star), and manage what line of the star you are drawing and what you are not according to time (build a small 'state-machine' that manages the stages).

You can take care of the fading using simple fade animation on this view at the proper stages.

yakobom
  • 2,630
  • 1
  • 23
  • 31