Android Color Between Two Colors, Based on Percentage

android color between two colors, based on percentage?

Ok, after 2 hours of converting to yuv, hsv, etc pp... I give up. I now do it just like this:

public class ColorUtils {
private static int FIRST_COLOR = Color.GREEN;
private static int SECOND_COLOR = Color.YELLOW;
private static int THIRD_COLOR = Color.RED;

public static int getColor(float p) {
int c0;
int c1;
if (p <= 0.5f) {
p *= 2;
c0 = FIRST_COLOR;
c1 = SECOND_COLOR;
} else {
p = (p - 0.5f) * 2;
c0 = SECOND_COLOR;
c1 = THIRD_COLOR;
}
int a = ave(Color.alpha(c0), Color.alpha(c1), p);
int r = ave(Color.red(c0), Color.red(c1), p);
int g = ave(Color.green(c0), Color.green(c1), p);
int b = ave(Color.blue(c0), Color.blue(c1), p);
return Color.argb(a, r, g, b);
}

private static int ave(int src, int dst, float p) {
return src + java.lang.Math.round(p * (dst - src));
}
}

By explicity using yellow as the middle color, the generated colors are brighter :-)

Anyway.. if someone has a good other solution, I would appreciate it.

Represent Percentage Value (0-100) in Color (from Red to Green)

This code is not optimized but it does what it is meant to do.

public class MainActivity extends Activity {

@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.screen_main);

final SeekBar sb = (SeekBar) findViewById(R.id.seekBar);
sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

@Override
public void onStopTrackingTouch(final SeekBar seekBar) {
}

@Override
public void onStartTrackingTouch(final SeekBar seekBar) {
}

@Override
public void onProgressChanged(final SeekBar seekBar,
final int progress, final boolean fromUser) {
update(seekBar);
}
});
update(sb);
}

private void update(final SeekBar sb) {
final RelativeLayout layout = (RelativeLayout) findViewById(R.id.layout);

final int colorStart = Color.parseColor("#BD4141");
final int colorEnd = Color.parseColor("#719D98");

layout.setBackgroundColor(interpolateColor(colorStart, colorEnd,
sb.getProgress() / 100f)); // assuming SeekBar max is 100
}

private float interpolate(final float a, final float b,
final float proportion) {
return (a + ((b - a) * proportion));
}

private int interpolateColor(final int a, final int b,
final float proportion) {
final float[] hsva = new float[3];
final float[] hsvb = new float[3];
Color.colorToHSV(a, hsva);
Color.colorToHSV(b, hsvb);
for (int i = 0; i < 3; i++) {
hsvb[i] = interpolate(hsva[i], hsvb[i], proportion);
}
return Color.HSVToColor(hsvb);
}

}

This answer is based on question and answers from android color between two colors, based on percentage?.

how to mix two color with different percent

You didn't clearly say why the result is disappointing, so I'm assuming it means the color transition you get is not as good you expected it to be.

Your general approach seems right, maybe you are just missing some detail so I will rewrite it in different terms. Let color1 and color2 be triples (R, G, B) where each of R, G, B is in range [0, 1]. If that is not the case, divide by 255 if that is the limit in your situation, and later multiply again by 255. Let s be the number of steps to transition from color1 to color2, here I'm including in s the initial frame with color1 but not the final frame with color2. At step k, you have a value p such that p = (s - k)/s. With p you obtain the color in frame k by doing color = p * color1 + (1 - p) * color2. Now you may want to multiply color by 255.

A pseudocode for this description is:

color1 = (R1, G1, B1)
color2 = (R2, G2, B2)
s = N

for k = 0 to s: # s + 1 steps, according to the description
p = (s - k) / s
color = (p * color1) + ((1 - p) * color2)

Note that at k = 0 you have only color1, and at k = s you get only color2. As you see, it is similar to what you posted with more details. Note that here I'm multiplying each of R, G, B by p.

Here are some examples transitioning from a yellow to some blue color, steps = 10, 25, 500 respectively.

Sample Image
Sample Image
Sample Image

How to color some percent of a layout?

You can start off with a ClipDrawable. This will clip another drawable — for instance, a ShapeDrawable — based on the drawable level.

Then in your timer callback:

    int level; // from 0 to 10000 = 100%

view.getBackground.setLevel(level);

Drawable#setLevel


EDIT: Here's an example:

  1. Define the shape drawable in /res/drawable. Call it bkgd_shape.xml.

    <?xml version="1.0" encoding="utf-8"?>
    <shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/background"/>
    </shape>
  2. Define the background drawable in /res/drawable. Let's call it bkgd_level.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <clip
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/bkgd_shape"
    android:clipOrientation="horizontal"
    android:gravity="left|clip_horizontal|fill_vertical"/>

    You might be able to put a color in directly for the drawable source, but I haven't tried it.

  3. Set it as the background of your layout:

        android:background="@drawable/bkgd_level"
  4. Call setLevel on the drawable:

        int level; // from 0 to 10000 = 100%

    view.getBackground.setLevel(level);

Filling listview row's color to some percentage

I think one option is described below:

I would created a List view and for each item in the list, I would create two Views:

  1. One TextView (to show the text options) -> Default is visible
  2. One View (to draw progress if user click in the list) -> Default is invisible.

Note: This simple View with progress will have same height for TextView. It is fully colored with background color (blue for example). Then, you can set how long this view should be by setting its weight (from 0 to 100). Weight will be dinamically changed in the adapter. Other properties you can set in layout resource file (list_view_each_row.xml).

Also, I believe you have to create your own custom list adapter (to handle properly if list should display text or progress). This custom list should extend BaseAdapter and should override mandatory methods.

So, after clicking in any option, you can change your adapter (you should inform your adapter that user cliecked in some option). Based on this new information, adapter can hide all TextViews and display only the Views with progress.

Below is a example code:
You can add security checks (null poiter) in the adapter. I used a simple array. You can change to ArrayList and add/removes items dinamically. Also, you can set progress values only inside "OnItemClickListener". It is just a example.

MainActivity

public class MainActivity extends Activity {

private MyCustomListAdapter adapter;

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

((ListView) findViewById(R.id.list_view)).setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Force list view to populate its content again (now, with progress instead of text)
adapter.setIfUserAlreadyClickedOption(true);
adapter.notifyDataSetChanged();
}
});

adapter = new MyCustomListAdapter();

// Set click to false (user did not clicked yet)
adapter.setIfUserAlreadyClickedOption(false);

// Set text and progress
adapter.setOptions(new String []{"Option1", "Option2", "Option3"});
adapter.setProgressBarValues(new float [] {50,75,25});
((ListView)findViewById(R.id.list_view)).setAdapter(adapter);
}
}

MyCustomListAdapter.java

public class MyCustomListAdapter extends BaseAdapter {

private boolean userAlreadyCliced;
private String [] stringTexts;
private float [] progressBarValues;

public MyCustomListAdapter() {
userAlreadyCliced = false;
}

public void setIfUserAlreadyClickedOption(boolean clicked) {
userAlreadyCliced = clicked;
}

public void setOptions(String [] text) {
stringTexts = text;
}

public void setProgressBarValues(float [] values) {
progressBarValues = values;
}

@Override
public int getCount() {
return stringTexts.length;
}

@Override
public Object getItem(int position) {
return stringTexts[position];
}

@Override
public long getItemId(int position) {
return 0;
}

@Override
public View getView(int position, View view, ViewGroup parentViewGroup) {
if(view == null) {
view = LayoutInflater.from(parentViewGroup.getContext()).inflate(R.layout.list_view_each_row, parentViewGroup, false);
}

if(userAlreadyCliced) {
// Hide Text
view.findViewById(R.id.progress_view).setVisibility(View.VISIBLE);

// Show Text and set progress
((LinearLayout.LayoutParams) view.findViewById(R.id.progress_view).getLayoutParams()).weight = progressBarValues[position];
view.findViewById(R.id.text_view).setVisibility(View.GONE);
} else {
// Hide Progress
view.findViewById(R.id.progress_view).setVisibility(View.GONE);

// Show and set text
view.findViewById(R.id.text_view).setVisibility(View.VISIBLE);
((TextView)view.findViewById(R.id.text_view)).setText(stringTexts[position]);
}
return view;
}
}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >

<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>

</LinearLayout>

list_view_each_row.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="100" >

<View
android:id="@+id/progress_view"
android:background="#0000FF"
android:layout_width="0dp"
android:layout_height="40dp"/>

<TextView
android:id="@+id/text_view"
android:visibility="visible"
android:layout_width="match_parent"
android:layout_height="40dp" />

</LinearLayout>

Percent color in Android for Material Design

The percentage are for visibility of the color

When we specify any color using hex format :

First 2 digit : visibility

After 6 digit : RRGGBB

So, the calculation example is :

(87)% of (100) decimel = 87 %   ->    convert to (87)% of (256) in hex 222.72 rounding to 223 which is (DF) in hex

So your color code = #DF607D8B -- primary

Same way, any perentage should be converted to hex

You can check table : here

How to get intermediate colors from one to another?

Suppose we have 2 Colors (R1,G1,B1) (R2,G2,B2) and N number of intermediate colors:

for i from 1 to N:
Ri = R1 + (R2-R1) * i / N
Bi = B1 + (B2-B1) * i / N
Gi = G1 + (G2-G1) * i / N
AddToArray(Ri,Gi,Bi)

Is that what you are looking for?

PS: I would recommend using the HSL color space instead of the RGB if you want to have a more natural color gradient.



Related Topics



Leave a reply



Submit