I have a Util class which is capable of creating color codes(decimal).
public class ColorUtils {
private static final String RED = "ff0000";
private static final String GREEN = "00ff00";
private static final String BLUE = "0000ff";
private static final String WHITE = "ffffff";
private static final int RADIX = 16;
public static int getColorShade(String deepShade, String lightShade, float percentage) {
if (percentage > 100) {
throw new RuntimeException("Percentage can not be more than 100");
}
int deepShadeCode = Integer.parseInt(deepShade, RADIX);
int lightShadeCode = Integer.parseInt(lightShade, RADIX);
int shadeDifference = deepShadeCode - lightShadeCode;
int shadeOffset = (int) (shadeDifference * percentage)/100;
return lightShadeCode + shadeOffset;
}
public static int getColorShade(String deepShade, float percentage) {
return getColorShade(deepShade, WHITE, percentage);
}
public static int getRedColorShade(float percentage) {
return getColorShade(RED, percentage);
}
public static int getGreenColorShade(float percentage) {
return getColorShade(GREEN, percentage);
}
public static int getBlueColorShade(float percentage) {
return getColorShade(BLUE, percentage);
}
public static int getWhite() {
return Integer.parseInt(WHITE, RADIX);
}
}
Is there any way to convert it to Android color?
All I could find out is ContextCompat.getColor(this,R.color.yourcolor)
but this will take resource id in second arguments, I don't want to make color pallets in color.xml. Is there a work around?
Don't know how you create the color, but if it can extract red, green, blue, then try this:
#ColorInt int color = Color.rgb(getRedColorShade(percentage), getGreenColorShade(percentage), getBlueColorShade(percentage));
Ref here, this time it's pretty sure that this method is added from API level 1 and can be used instead of valueOf
I have a problem with a disappearing of a custom view, which I've created programmatically and added to the item container (RelativeLayout), when I scroll it down and up. It builds successfully.
But after scrolling, I have this result in the same item - an empty container..
Custom View
public class WaveFormView extends View {
Paint p;
Paint pTop;
Paint pBottom;
Rect rect;
Rect rect1;
int [] amplitudeArray;
int amplitudeArraySize;
int leftPointX;
int rightPointX;
int index;
boolean isPlay;
public static final int MAX_AMPLITUDE = 32;//was 1000
public static final int SIZE_OF_BAR_WAVE_FORM = 98;
public static final int BAR_SIZE_AND_INTERVAL = 5;
private static final float screenDensity = Utils.getDisplayDensity();
public WaveFormView(Context context, int [] amplitudeArray, boolean isPlay, int index) {
super(context);
p = new Paint();
p.setColor(getResources().getColor(R.color.color_wave_from_grey));
pTop = new Paint();
pTop.setColor(getResources().getColor(R.color.color_wave_form_play_top));
pBottom = new Paint();
pBottom.setColor(getResources().getColor(R.color.color_wave_form_play_bottom));
this.amplitudeArray = amplitudeArray;
amplitudeArraySize = amplitudeArray.length;
this.isPlay = isPlay;
this.index = index;
}
#Override
protected void onDraw(Canvas canvas) {
if(!isPlay){
buildWaveForm(canvas);
}
else{
buildWaveFormWhenPlay(canvas);
}
}
private void buildWaveForm(Canvas canvas){
int oneDp = (int) (1*screenDensity);
int fourDp = (int) (4*screenDensity);
int amplitudeDp = 0;
int startBottomY = (int) (MAX_AMPLITUDE*screenDensity) + oneDp;
p.setColor(getResources().getColor(R.color.color_wave_from_grey));
for (int i = 0; i < amplitudeArraySize; i++){
p.setStyle(Paint.Style.FILL_AND_STROKE);
leftPointX += oneDp;
rightPointX = leftPointX+fourDp;
amplitudeDp = (int) (amplitudeArray[i]*screenDensity);
rect = new Rect(leftPointX, startBottomY, rightPointX, startBottomY + amplitudeDp);
rect1 = new Rect(leftPointX, startBottomY-oneDp-amplitudeDp, rightPointX, startBottomY-oneDp);
canvas.drawRect(rect, p);
canvas.drawRect(rect1, p);
leftPointX+=fourDp;
}
}
private void buildWaveFormWhenPlay(Canvas canvas){
...}
Adapter
public class PostTimeLineAdapter extends
RecyclerView.Adapter<PostTimeLineHolder> ...
#Override
public void onBindViewHolder(final PostTimeLineHolder holder, final int position) { ...
holder.homeItemContainerWaveForm.addView(new WaveFormView(context,bufferArray, false, -1));...}
Holder
public class PostTimeLineHolder extends RecyclerView.ViewHolder {
...
public RelativeLayout homeItemContainerWaveForm;
public PostTimeLineHolder(View itemView) {
super(itemView);
...
this.homeItemContainerWaveForm = (RelativeLayout) itemView.findViewById(R.id.home_item_sound_container_wave_forms);}}
Thanks for all your answers!
The reason of that weird behavior was in not zeroing after operator for those parameters: leftPointX and rightPointX, in the method buildWaveForm. If you set zeros for them after operator for, method buildWaveForm works acuratelly.
Background
After a lot of searching for the best solution of auto-resizing TextView (according to content, size, min&max lines, and font-size restrictions), I've made a merged solution for it all, here.
NOTE: I don't use other solutions because they don't work well, each has its own issues (something isn't supported, text goes outside of TextView, text get truncated,...) .
Demonstration of it works:
https://raw.githubusercontent.com/AndroidDeveloperLB/AutoFitTextView/master/animationPreview.gif
The problem
On some cases, the last character of one line wraps to the next line, as such:
Green is the boundaries of the TextView, red is outside of it.
The code
Basically, given the size of the TextView, its min&max font size and min&max lines, and the content (text) that's supposed to be within, it finds (using binary search) what font size should fit within the boundaries of the TextView.
The code is available in Github already, but here it is just in case :
public class AutoResizeTextView extends AppCompatTextView {
private static final int NO_LINE_LIMIT = -1;
private final RectF _availableSpaceRect = new RectF();
private final SizeTester _sizeTester;
private float _maxTextSize, _spacingMult = 1.0f, _spacingAdd = 0.0f, _minTextSize;
private int _widthLimit, _maxLines;
private boolean _initialized = false;
private TextPaint _paint;
private interface SizeTester {
/**
* #param suggestedSize Size of text to be tested
* #param availableSpace available space in which text must fit
* #return an integer < 0 if after applying {#code suggestedSize} to
* text, it takes less space than {#code availableSpace}, > 0
* otherwise
*/
int onTestSize(int suggestedSize, RectF availableSpace);
}
public AutoResizeTextView(final Context context) {
this(context, null, android.R.attr.textViewStyle);
}
public AutoResizeTextView(final Context context, final AttributeSet attrs) {
this(context, attrs, android.R.attr.textViewStyle);
}
public AutoResizeTextView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
// using the minimal recommended font size
_minTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics());
_maxTextSize = getTextSize();
_paint = new TextPaint(getPaint());
if (_maxLines == 0)
// no value was assigned during construction
_maxLines = NO_LINE_LIMIT;
// prepare size tester:
_sizeTester = new SizeTester() {
final RectF textRect = new RectF();
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public int onTestSize(final int suggestedSize, final RectF availableSPace) {
_paint.setTextSize(suggestedSize);
final TransformationMethod transformationMethod = getTransformationMethod();
final String text;
if (transformationMethod != null)
text = transformationMethod.getTransformation(getText(), AutoResizeTextView.this).toString();
else
text = getText().toString();
final boolean singleLine = getMaxLines() == 1;
if (singleLine) {
textRect.bottom = _paint.getFontSpacing();
textRect.right = _paint.measureText(text);
} else {
final StaticLayout layout = new StaticLayout(text, _paint, _widthLimit, Alignment.ALIGN_NORMAL, _spacingMult, _spacingAdd, true);
// return early if we have more lines
if (getMaxLines() != NO_LINE_LIMIT && layout.getLineCount() > getMaxLines())
return 1;
textRect.bottom = layout.getHeight();
int maxWidth = -1;
for (int i = 0; i < layout.getLineCount(); i++)
if (maxWidth < layout.getLineRight(i) - layout.getLineLeft(i))
maxWidth = (int) layout.getLineRight(i) - (int) layout.getLineLeft(i);
textRect.right = maxWidth;
}
textRect.offsetTo(0, 0);
if (availableSPace.contains(textRect))
// may be too small, don't worry we will find the best match
return -1;
// else, too big
return 1;
}
};
_initialized = true;
}
#Override
public void setAllCaps(boolean allCaps) {
super.setAllCaps(allCaps);
adjustTextSize();
}
#Override
public void setTypeface(final Typeface tf) {
super.setTypeface(tf);
adjustTextSize();
}
#Override
public void setTextSize(final float size) {
_maxTextSize = size;
adjustTextSize();
}
#Override
public void setMaxLines(final int maxlines) {
super.setMaxLines(maxlines);
_maxLines = maxlines;
adjustTextSize();
}
#Override
public int getMaxLines() {
return _maxLines;
}
#Override
public void setSingleLine() {
super.setSingleLine();
_maxLines = 1;
adjustTextSize();
}
#Override
public void setSingleLine(final boolean singleLine) {
super.setSingleLine(singleLine);
if (singleLine)
_maxLines = 1;
else _maxLines = NO_LINE_LIMIT;
adjustTextSize();
}
#Override
public void setLines(final int lines) {
super.setLines(lines);
_maxLines = lines;
adjustTextSize();
}
#Override
public void setTextSize(final int unit, final float size) {
final Context c = getContext();
Resources r;
if (c == null)
r = Resources.getSystem();
else r = c.getResources();
_maxTextSize = TypedValue.applyDimension(unit, size, r.getDisplayMetrics());
adjustTextSize();
}
#Override
public void setLineSpacing(final float add, final float mult) {
super.setLineSpacing(add, mult);
_spacingMult = mult;
_spacingAdd = add;
}
/**
* Set the lower text size limit and invalidate the view
*
* #param minTextSize
*/
public void setMinTextSize(final float minTextSize) {
_minTextSize = minTextSize;
adjustTextSize();
}
private void adjustTextSize() {
// This is a workaround for truncated text issue on ListView, as shown here: https://github.com/AndroidDeveloperLB/AutoFitTextView/pull/14
// TODO think of a nicer, elegant solution.
// post(new Runnable()
// {
// #Override
// public void run()
// {
if (!_initialized)
return;
final int startSize = (int) _minTextSize;
final int heightLimit = getMeasuredHeight() - getCompoundPaddingBottom() - getCompoundPaddingTop();
_widthLimit = getMeasuredWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight();
if (_widthLimit <= 0)
return;
_paint = new TextPaint(getPaint());
_availableSpaceRect.right = _widthLimit;
_availableSpaceRect.bottom = heightLimit;
superSetTextSize(startSize);
// }
// });
}
private void superSetTextSize(int startSize) {
int textSize = binarySearch(startSize, (int) _maxTextSize, _sizeTester, _availableSpaceRect);
super.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
}
private int binarySearch(final int start, final int end, final SizeTester sizeTester, final RectF availableSpace) {
int lastBest = start, lo = start, hi = end - 1, mid;
while (lo <= hi) {
mid = lo + hi >>> 1;
final int midValCmp = sizeTester.onTestSize(mid, availableSpace);
if (midValCmp < 0) {
lastBest = lo;
lo = mid + 1;
} else if (midValCmp > 0) {
hi = mid - 1;
lastBest = hi;
} else return mid;
}
// make sure to return last best
// this is what should always be returned
return lastBest;
}
#Override
protected void onTextChanged(final CharSequence text, final int start, final int before, final int after) {
super.onTextChanged(text, start, before, after);
adjustTextSize();
}
#Override
protected void onSizeChanged(final int width, final int height, final int oldwidth, final int oldheight) {
super.onSizeChanged(width, height, oldwidth, oldheight);
if (width != oldwidth || height != oldheight)
adjustTextSize();
}
}
The question
Why does it occur? What can I do to fix this?
Seems it's possible using support library:
<TextView
android:layout_width="250dp" android:layout_height="wrap_content" android:background="#f00"
android:breakStrategy="balanced" android:hyphenationFrequency="none"
android:text="This is an example text" android:textSize="30dp" app:autoSizeTextType="uniform"/>
Sadly, it has 2 disadvantages:
Doesn't always spread words nicely. Reported here.
Requires Android API 23 and above (here).
More information here.
I had similar problem in my project. Long-time Googling, StackOverflow (with your question among others). Nothing.
And my final "solution" was BreakIterator for words + measure them all to check this situation.
UPDATE (2018-08-10):
static public boolean isTextFitWidth(final #Nullable String source, final #NonNull BreakIterator bi, final #NonNull TextPaint paint, final int width, final float textSize)
{
if (null == source || source.length() <= 0) {
return true;
}
TextPaint paintCopy = new TextPaint();
paintCopy.set(paint);
paintCopy.setTextSize(textSize);
bi.setText(source);
int start = bi.first();
for (int end = bi.next(); BreakIterator.DONE != end; start = end, end = bi.next()) {
int wordWidth = (int)Math.ceil(paintCopy.measureText(source, start, end));
if (wordWidth > width) {
return false;
}
}
return true;
}
static public boolean isTextFitWidth(final #NonNull TextView textView, final #NonNull BreakIterator bi, final int width, final #Nullable Float textSize)
{
final int textWidth = width - textView.getPaddingLeft() - textView.getPaddingRight();
return isTextFitWidth(textView.getText().toString(), bi, textView.getPaint(), textWidth,
null != textSize ? textSize : textView.getTextSize());
}
I have checked the suggested question here, but when I checked the documentation regarding the method getNetworkInfo()here, there was no documentation regarding the possible integer values this method could handle. For an example, if I passed 0 to the getNetworkInfo() this means I am checking he mobile network, and if it is 1, I am checking the status of the WiFi.
Is there any other possible values? Why they are not in the documentation?
From the docs: http://developer.android.com/reference/android/net/ConnectivityManager.html
public static final int TYPE_NONE = -1;
public static final int TYPE_MOBILE = 0;
public static final int TYPE_WIFI = 1;
public static final int TYPE_MOBILE_MMS = 2;
public static final int TYPE_MOBILE_SUPL = 3;
public static final int TYPE_MOBILE_DUN = 4;
public static final int TYPE_MOBILE_HIPRI = 5;
public static final int TYPE_WIMAX = 6;
public static final int TYPE_BLUETOOTH = 7;
public static final int TYPE_DUMMY = 8;
public static final int TYPE_ETHERNET = 9;
public static final int TYPE_MOBILE_FOTA = 10;
public static final int TYPE_MOBILE_IMS = 11;
public static final int TYPE_MOBILE_CBS = 12;
public static final int TYPE_WIFI_P2P = 13;
public static final int TYPE_MOBILE_IA = 14;
I am trying to do resampling in android using this library https://github.com/intervigilium/libresample/blob/master/src/net/sourceforge/resample/Resample.java#L6
but I dont know exactly what to fill in the Parameters
I want to Resample an audio file
File mySound = new File("/mySound.wav");
to 44,100 kHz
how do i do it with this library: Library Code shown below..
package net.sourceforge.resample;
public class Resample {
public static final int DEFAULT_BUFFER_SIZE = 4096;
public static final int MAX_CHANNELS = 2;
public static final int CHANNEL_MONO = 0;
public static final int CHANNEL_LEFT = 0;
public static final int CHANNEL_RIGHT = 1;
private static final String RESAMPLE_LIB = "resample";
static {
System.loadLibrary(RESAMPLE_LIB);
}
public static native void downmix(short outputBuffer[], short inputLeft[], short inputRight[], int numSamples);
public static native int resample(double factor, short inputBuffer[], short outputBuffer[], int numSamples);
public static native void initialize(int inputRate, int outputRate, int bufferSize, int channels);
public static native double getFactor();
public static native int process(short inputBuffer[], short outputBuffer[], int channel, boolean isLast);
public static native void close();
}