I am trying to create custom seek bar in android with multicolor. I tried below code
customseekbar.java
int proBarWidth = getWidth();
int proBarHeight = getHeight();
int thumboffset = getThumbOffset();
int lastproX = 0;
int proItemWidth, proItemRight;
for (int i = 0; i < mproItemsList.size(); i++) {
proItem proItem = mproItemsList.get(i);
Paint proPaint = new Paint();
proPaint.setColor(getResources().getColor(proItem.color));
proItemWidth = (int) (proItem.proItemPercentage
* proBarWidth / 100);
proItemRight = lastproX + proItemWidth;
// for last item give right of the pro item to width of the
// pro bar
if (i == mproItemsList.size() - 1
&& proItemRight != proBarWidth) {
proItemRight = proBarWidth;
}
Rect proRect = new Rect();
proRect.set(lastproX, thumboffset / 2, proItemRight,
proBarHeight - thumboffset / 2);
canvas.drawRect(proRect, proPaint);
lastproX = proItemRight;
}
super.onDraw(canvas);
view
<mypackage.customseekbar
android:id="#+id/customseekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0"
android:progressDrawable="#android:color/transparent"
android:thumb="#drawable/seek_thumb_normal"
android:thumbOffset="12dp" />
I used this method in MainMenuActivity. It gives me result something like below. I referred this link https://azzits.wordpress.com/2013/11/17/customseekbar/
But I am expecting something like below
Is there any way to draw this vertical gapped lines? How can I draw this vertical lines?
Progress bar with divider is a good place to look as mentioned by #Nilesh Rathod. Rather than using canvas.drawRect() you can use canvas.drawRoundRect(); Short example:
for (int i = 0; i < NUM_SEGMENTS; i++) {
float loLevel = i / (float) NUM_SEGMENTS;
float hiLevel = (i + 1) / (float) NUM_SEGMENTS;
if (loLevel <= level && level <= hiLevel) {
float middle = mSegment.left + NUM_SEGMENTS * segmentWidth * (level - loLevel);
canvas.drawRoundRect(mSegment.left, mSegment.top, middle, mSegment.bottom, mPaint);
mPaint.setColor(mBackground);
canvas.drawRoundRect(middle, mSegment.top, mSegment.right, mSegment.bottom, mPaint);
} else {
canvas.drawRoundRect(mSegment, mPaint);
}
mSegment.offset(mSegment.width() + gapWidth, 0);
}
I give full credit to the code above to the creator of the aforementioned link and don't claim any of it as mine as I am just illustrating the change that should be made to reach the desired effect. Please let me know if you run into further issues.
Related
I am trying to create a text sticker in android. I am creating a text sticker on one of my phones and then saving the text size in the DP.
Then on another phone, I am loading the same text with the same DP and converting the DP value to pixel. Then calling the method
TextPaint.setTextSize(pixelValue)
But the output is different on both phones. I also tried replacing DP with SP, but it seems that's not the solution.
Also one more thing, I am determining the width and height of my view based on a drawable(res) width height.
Here is code of that drawable
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#android:color/transparent" />
<size android:width="200dp" android:height="50dp" />
</shape>
But this doesn't seem to be problem as the values are in DP in the drawable file.
Here is the constructor of text sticker.
public DynamicTextSticker(#NonNull Context context, #Nullable Drawable drawable, String text) {
this.context = context;
this.drawable = drawable;
if (drawable == null) {
this.drawable = ContextCompat.getDrawable(context, R.drawable.sticker_transparent_background);
}
textPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
minTextSizePixels = DensityUtils.px2dp(context, 6);
maxTextSizePixels = DensityUtils.px2dp(context, 32);
alignment = Layout.Alignment.ALIGN_CENTER;
textPaint.setTextSize(maxTextSizePixels);
realBounds = new Rect(0, 0, getWidth(), getHeight());
textRect = new Rect(0, 0, getWidth(), getHeight());
}
draw method
#Override public void draw(#NonNull Canvas canvas) {
Matrix matrix = getMatrix();
canvas.save();
canvas.concat(matrix);
if (drawable != null) {
drawable.setBounds(realBounds);
drawable.draw(canvas);
}
canvas.restore();
canvas.save();
canvas.concat(matrix);
if (textRect.width() == getWidth()) {
int dy = getHeight() / 2 - staticLayout.getHeight() / 2;
// center vertical
canvas.translate(0, dy);
} else {
int dx = textRect.left;
int dy = textRect.top + textRect.height() / 2 - staticLayout.getHeight() / 2;
canvas.translate(dx, dy);
}
staticLayout.draw(canvas);
canvas.restore();
}
here is the resize method where the static layout is initialized
final int availableHeightPixels = textRect.height();
final int availableWidthPixels = textRect.width();
final CharSequence text = getText();
// Safety check
// (Do not resize if the view does not have dimensions or if there is no text)
if (text == null
|| text.length() <= 0
|| availableHeightPixels <= 0
|| availableWidthPixels <= 0
|| maxTextSizePixels <= 0) {
return this;
}
float targetTextSizePixels = maxTextSizePixels;
int targetTextHeightPixels =
getTextHeightPixels(text, availableWidthPixels, targetTextSizePixels);
// Until we either fit within our TextView
// or we have reached our minimum text size,
// incrementally try smaller sizes
while (targetTextHeightPixels > availableHeightPixels
&& targetTextSizePixels > minTextSizePixels) {
targetTextSizePixels = Math.max(targetTextSizePixels - 2, minTextSizePixels);
targetTextHeightPixels =
getTextHeightPixels(text, availableWidthPixels, targetTextSizePixels);
}
// If we have reached our minimum text size and the text still doesn't fit,
// append an ellipsis
// (NOTE: Auto-ellipsize doesn't work hence why we have to do it here)
if (targetTextSizePixels == minTextSizePixels
&& targetTextHeightPixels > availableHeightPixels) {
// Make a copy of the original TextPaint object for measuring
TextPaint textPaintCopy = new TextPaint(textPaint);
textPaintCopy.setTextSize(targetTextSizePixels);
// Measure using a StaticLayout instance
StaticLayout staticLayout =
new StaticLayout(text, textPaintCopy, availableWidthPixels, Layout.Alignment.ALIGN_NORMAL,
lineSpacingMultiplier, lineSpacingExtra, false);
// Check that we have a least one line of rendered text
if (staticLayout.getLineCount() > 0) {
// Since the line at the specific vertical position would be cut off,
// we must trim up to the previous line and add an ellipsis
int lastLine = staticLayout.getLineForVertical(availableHeightPixels) - 1;
if (lastLine >= 0) {
int startOffset = staticLayout.getLineStart(lastLine);
int endOffset = staticLayout.getLineEnd(lastLine);
float lineWidthPixels = staticLayout.getLineWidth(lastLine);
float ellipseWidth = textPaintCopy.measureText(mEllipsis);
// Trim characters off until we have enough room to draw the ellipsis
while (availableWidthPixels < lineWidthPixels + ellipseWidth) {
endOffset--;
lineWidthPixels =
textPaintCopy.measureText(text.subSequence(startOffset, endOffset + 1).toString());
}
setText(text.subSequence(0, endOffset) + mEllipsis);
}
}
}
textPaint.setTextSize(targetTextSizePixels);
this.targetTextSizePixel = targetTextSizePixels;
staticLayout =
new StaticLayout(this.text, textPaint, textRect.width(), alignment, lineSpacingMultiplier,
lineSpacingExtra, true);
return this;
here is the getWidth and getHeight method
#Override public int getWidth() {
return drawable.getIntrinsicWidth();
}
#Override public int getHeight() {
return drawable.getIntrinsicHeight();
}
I tried several ways but none of them worked for me.
I think the problem is not with text size. but the problem might be with drawable. But I don't know what possibly could go wrong with that, as I have used DP unit everywhere.
**If i forget to add any code please tell me I will attach it as well**
I am new to android so I am not sure the reason behind this problem.
Thanks for your help.
I am doing this in processing which is essentially java and I have never attempted anything like this before. Can't find any examples of collision detection using arrays to map the pixels.
I am not really trying to make them realistic collisions. I was thinking it would have the same response as if it hit a wall which is just for it to change directions in whatever axis is appropriate for the wall it hit.
I have tried checking if the x and y position are the same but can't seem to make that work. I'd appreciate any input on this.
import java.util.Arrays;
int numOfParticles = 10;
float[] x = new float[numOfParticles]; //initial position of y only matters
float[] px = new float[numOfParticles];
float[] y = new float[numOfParticles];
float[] py = new float[numOfParticles];
int speed = 10;//inversly related to speed
float[] xIncrement = new float[numOfParticles]; //the ratio of increments determines the pattern
float[] yIncrement = new float[numOfParticles]; // it is the slope of the line
//float xIncrement = 10/speed; //the ratio of increments determines the pattern
//float yIncrement = 11/speed; // it is the slope of the line
color currentColor;
int alpha = 100;//range of 0-255
//radius of ball
int radius = 1;
//thickness of line behind ball
int thickness = 5;
int rateOfColor = 5; //this is inversely related to rate but also changes the range of colors
int maxColor = 255;
int minColor = 0;
void setup(){
size(500,500);
background(0);
colorMode(HSB);
strokeWeight(thickness);
frameRate(60);
//initialize particles
for(int i = 0;i<numOfParticles;i++){
xIncrement[i] = random(0,100)/speed; //the ratio of increments determines the pattern
yIncrement[i] = random(0,100)/speed; // it is the slope of the line
x[i] = random(0,width);
px[i] = x[i];
y[i] = random(0,height);
py[i] = y[i];
}
//you can either initialize all of them individually or do a random one
//x[0] = 0;
//px[0] = x[0];
//y[0] = 450;
//py[0] = y[0];
//x[1] = width;
//px[1] = x[1];
//y[1] = 450;
//py[1] = y[1];
}
void draw(){
background(0); //comment out for criss cross
for(int i = 0; i < numOfParticles; i++){
particle(i);
}
}
void particle(int particleNum){
currentColor = color(minColor + (x[particleNum]/rateOfColor)%maxColor,255,255,alpha);
stroke(currentColor);
fill(currentColor);
ellipse(x[particleNum],y[particleNum],radius,radius);
line(px[particleNum],py[particleNum],x[particleNum],y[particleNum]);
px[particleNum] = x[particleNum];
py[particleNum] = y[particleNum];
y[particleNum]+= yIncrement[particleNum];
x[particleNum]+= xIncrement[particleNum];
if(x[particleNum] > width + 1 || x[particleNum] < 0){
x[particleNum] -= 2*xIncrement[particleNum];
xIncrement[particleNum]*=-1;
}
if( y[particleNum] > height + 1 || y[particleNum] < 0){
y[particleNum] -= 2*yIncrement[particleNum];
yIncrement[particleNum]*=-1;
}
//if(Arrays.binarySearch(x,x[particleNum]) >= 0 && Arrays.binarySearch(y,y[particleNum]) >= 0){
// xIncrement[particleNum]*=-1;
// yIncrement[particleNum]*=-1;
// print("*\n");
// stop();
//}
print("x[0] = " + x[0] + "\n");
print("x[1] = " + x[1] + "\n");
print("y[0] = " + y[0] + "\n");
print("y[1] = " + y[1] + "\n");
}
Stack Overflow isn't really designed for general "how do I do this" type questions. It's for specific "I tried X, expected Y, but got Z instead" type questions. But I'll try to help in a general sense:
You need to break your problem down into smaller pieces and then take those pieces on one at a time. Don't worry about the whole particle system. Make it work for a single particle. Do some research on collision detection.
Then if you get stuck, you can post a more specific question along with a MCVE. Good luck.
I'm using the barcode-reader example from Google's Android Vision API.
The preview size doesn't seem to fill up the whole space available (I'm using a Nexus 4 and there is a white unused space to the right of preview, about 1/3 of the width).
I would like to be able to run this example on various devices and always have it fill up the whole space available.
So the bit I've been playing with is:
CameraSource.Builder builder = new CameraSource.Builder(getApplicationContext(), barcodeDetector).setFacing(CameraSource.CAMERA_FACING_BACK).setRequestedPreviewSize(?, ?).setRequestedFps(15.0f);
Any ideas?
Thanks!
just remove or comment below code from CameraSourcePreview class
if (childHeight > layoutHeight) {
childHeight = layoutHeight;
childWidth = (int)(((float) layoutHeight / (float) height) * width);
}
and use layoutHeight instead of childHeight of "CameraSourcePreview" class in this loop - for (int i = 0; i < getChildCount(); ++i){...}
if (mCameraSource != null)
{
Size size = mCameraSource.getPreviewSize();
if (size != null)
{
width = size.getWidth();
height = size.getHeight();
}
}
// Swap width and height sizes when in portrait, since it will be rotated 90 degrees
if (isPortraitMode())
{
int tmp = width;
//noinspection SuspiciousNameCombination
width = height;
height = tmp;
}
final int layoutWidth = right - left;
final int layoutHeight = bottom - top;
// Computes height and width for potentially doing fit width.
int childWidth = layoutWidth;
int childHeight = (int) (((float) layoutWidth / (float) width) * height);
for (int i = 0; i < getChildCount(); ++i)
{
getChildAt(i).layout(0, 0, childWidth, layoutHeight);
}
try
{
startIfReady();
}
catch (SecurityException se)
{
Log.e(TAG, "Do not have permission to start the camera", se);
}
catch (IOException e)
{
Log.e(TAG, "Could not start camera source.", e);
}
}
There are two ways to make the camera image fill the entire screen.
Akesh Dubey's answer, which displays the whole image by stretching it to fit the layout's width and height. However, aspect ratio is not preserved.
My answer below, which crops the image to make it fit without sacrificing aspect ratio.
In order to crop-fit the image, all you have to do is change one > into a <. Find the below if-statement and change the condition like so:
if (childHeight < layoutHeight) {
childHeight = layoutHeight;
childWidth = (int)(((float) layoutHeight / (float) height) * width);
}
I am using this method with AndEngine to add a sprite to the screen and make it move across the screen.
private void addFace() {
Random rand = new Random();
float x = (int) mCamera.getHeight() - mBallTextureRegion.getHeight();
float minY = mBallTextureRegion.getHeight();
float maxY = (int)(mCamera.getWidth() + mBallTextureRegion.getWidth());
float rangeY = maxY - minY;
float y = rand.nextInt((int)rangeY) + minY;
this.mFaceCount++;
Log.e("Faces: ", "Face" + this.mFaceCount);
Sprite face = null;
Body body = null;
face = new Sprite(x, y, this.mBallTextureRegion.clone());
body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);
this.mScene.attachChild(face);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(face, body, true, true));
int minDuration = 2;
int maxDuration = 4;
int rangeDuration = maxDuration - minDuration;
int actualDuration = rand.nextInt(rangeDuration) + minDuration;
MoveXModifier mod = new MoveXModifier(actualDuration, face.getX(), - face.getWidth());
face.registerEntityModifier(mod);
}
What i would like to do is, instead of the Random position being selected and the sprite being added to the left side of the Scene, i would like for it to be added to the Top and fall down.
I basically want to flip the direction,
I just cant figure out how. Everything i tried was no luck.
Any ideas or suggestions?
While I don't know much about Andengine, I suspect you would want to change these lines:
float x = (int) mCamera.getHeight() - mBallTextureRegion.getHeight();
float y = rand.nextInt((int)rangeY) + minY;
MoveXModifier mod = new MoveXModifier(actualDuration, face.getX(), - face.getWidth());
Flip the x and y statements, but set y to -mBallTextureRegion.getHeight() if you want it to appear outside the screen.
For the MoveXModifier, I would guess there is a corresponding MoveYModifier (use face.getY() and -face.getHeight() respectively)
I was able to create a single bar graph using the code from Samir Talwar by modifying the renderer as the following:
vis.setRendererFactory(new RendererFactory() {
Renderer yAxisRenderer = new AxisRenderer(Constants.RIGHT, Constants.TOP);
Renderer xAxisRenderer = new AxisRenderer(Constants.CENTER, Constants.FAR_BOTTOM);
Renderer barRenderer = new ShapeRenderer() {
protected Shape getRawShape(VisualItem item) {
double x = item.getX();
double y = item.getY();
if (Double.isNaN(x) || Double.isInfinite(x))
x = getInsets().left + axisWidth + totalBarWidth / 2;
if (Double.isNaN(y) || Double.isInfinite(y))
y = 0;
double width = totalBarWidth / (barCount + 1) - barGap;
double height = getHeight() - getInsets().bottom - axisHeight - y;
x -= width / 2;
item.setFillColor(item.getStrokeColor());
return rectangle(x, y, width, height);
}
};
public Renderer getRenderer(VisualItem item) {
return item.isInGroup("ylab") ? yAxisRenderer :
item.isInGroup("xlab") ? xAxisRenderer :
barRenderer;
}
Anyhow, I have tried look on the possibility on creating clustered bar graphs where there are multiple bar for a single value but having difficulties. Also, the reason why I do not use JFreechart is because I need prefuse's filtering and searching functions which prove to be very useful in terms of analysis in my research.