How to make an Android progressbar with rounded loaderbar? - android

How do you make a progressbar with rounded corner at the right side (the end), not only in the left side (the start). What I currently have is nearly the layout what I want but the progressbar loader is just a straight vertical line, I'd like to get this line rounded.

Basically you should make a custom Widget, so you can cutomize it to your taste.
Here is a tutorial on exactly what you're looking for. link!

So what I ended up doing this in xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/white"
android:id="#+id/splash_linear">
<FrameLayout
android:layout_width="144dp"
android:layout_height="13dp"
android:layout_gravity="center"
android:layout_marginTop="20dp">
<View android:id="#+id/progress_horizontal"
android:background="#drawable/progress_background"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<View android:id="#+id/progress_horizontal_bar"
android:background="#drawable/progress_bar"
android:layout_width="0dp"
android:layout_height="match_parent"/>
</FrameLayout>
</LinearLayout>
Then in code:
public void updateProgress(int percent) {
int progressBarSizeDp = 144; // the size of the progressbar
float scale = (float) (progressBarSizeDp/100.0);
int progressSize = (int) (percent * scale);
if(progressSize > progressBarSizeDp) {
progressSize = progressBarSizeDp;
} else if(progressSize < 20) {
progressSize = 20;
}
View progressBar = (View) findViewById(R.id.progress_horizontal_bar);
int py = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, progressSize, getResources().getDisplayMetrics());
LayoutParams params = new FrameLayout.LayoutParams(py, LayoutParams.MATCH_PARENT);
progressBar.setLayoutParams(params);
View splashMain = (View) findViewById(R.id.splash_linear);
splashMain.invalidate();
}

Found a nice link:
Custom progress bar with rounded corners
Basically it uses a custom RelativeLayout and a 9-patch approach to draw the rounded progress bar.

Related

Get the position of each corner of a view, then add a view at the position

I am working on an android project where I have a custom view. When the custom view is clicked, I want a to put a view (a circle) at each corner of the view.
At the moment I'm just trying to get it work in the top left corner but it ends up in the middle.
Below is my click function for adding the view.
View view = LayoutInflater.from(getContext()).inflate(R.layout.view, this, false);
TextView textItem = view.findViewById(R.id.lblItemText);
textItem.setText("View: " + counter);
view.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
Anchor anchor1 = new Anchor(getContext());
anchor1.setLeft(v.getLeft());
anchor1.setTop(CustomView.this.getTop());
CustomView.this.addView(anchor1);
}
});
The custom view is hosted inside a relative layout. The custom view extends RelativeLayout and the anchor view which is supposed to go into the top left corner of the custom view extends button.
The anchor constructor contains the following:
public Anchor(Context context)
{
super(context);
this.setBackgroundResource(R.drawable.anchor);
this.setPadding(0,0,0,0);
this.setWidth(1);
this.setHeight(1);
}
For some reason the anchor is appearing in the middle instead of being on the corner as shown below
Below is kind of expecting.
UPDATE
After a couple of days made some progress and I do have it working, except its using hardcoded values to get it in the right position, which doesn't seem right. I'm guessing this will only work on the specific device I'm testing on, another device with another resolution will be positioned wrong.
Below is the code I have that hopefully shows what is I am trying to achieve along with a screenshot as to what I have now.
private void createAnchorPoints()
{
//Main View
ViewGroup mainView = activity.findViewById(android.R.id.content);
int[] viewToBeResizedLoc = new int[2];
viewToBeResized.getLocationOnScreen(viewToBeResizedLoc);
//Add top left anchor
Anchor topLeftAnchor = new Anchor(context, Anchor.ResizeMode.TOP_LEFT);
FrameLayout.LayoutParams topLeftParms = new FrameLayout.LayoutParams(150,150);
topLeftParms.leftMargin = viewToBeResizedLoc[0] - 50;
topLeftParms.topMargin = viewToBeResizedLoc[1] - viewToBeResized.getHeight() - 30;
topLeftAnchor.setLayoutParams(topLeftParms);
mainView.addView(topLeftAnchor);
//Add top right anchor
Anchor topRightAnchor = new Anchor(context, Anchor.ResizeMode.TOP_RIGHT);
FrameLayout.LayoutParams topRightParms = new FrameLayout.LayoutParams(150, 150);
topRightParms.leftMargin = topLeftParms.leftMargin + viewToBeResized.getWidth() - 40;
topRightParms.topMargin = topLeftParms.topMargin;
topRightAnchor.setLayoutParams(topRightParms);
mainView.addView(topRightAnchor);
//Add bottom left anchor
Anchor bottomLeftAnchor = new Anchor(context, Anchor.ResizeMode.BOTTOM_LEFT);
FrameLayout.LayoutParams bottomLeftParms = new FrameLayout.LayoutParams(150, 150);
bottomLeftParms.leftMargin = topLeftParms.leftMargin;
bottomLeftParms.topMargin = topLeftParms.topMargin + viewToBeResized.getHeight() - 40;
bottomLeftAnchor.setLayoutParams(bottomLeftParms);
mainView.addView(bottomLeftAnchor);
//Add bottom right anchor
Anchor bottomRightAnchor = new Anchor(context, Anchor.ResizeMode.BOTTOM_RIGHT);
FrameLayout.LayoutParams bottomRightParms = new FrameLayout.LayoutParams(150, 150);
bottomRightParms.leftMargin = topRightParms.leftMargin;
bottomRightParms.topMargin = bottomLeftParms.topMargin;
bottomRightAnchor.setLayoutParams(bottomRightParms);
mainView.addView(bottomRightAnchor);
}
Since the top-level layout is a RelativeLayout, you will need to use the view positioning that is available to RelativeLayout to achieve what you want. (See the documentation.)
Here is a mock-up of what you want to achieve in XML. This mock-up will demonstrate how we can approach the actual solution. I am using standard views, but it shouldn't matter. The technique will apply to your custom views. The image is from Android Studio's designer, so no code was used to create the image.
activity_main.xml
<RelativeLayout
android:id="#+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:id="#+id/customView"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_centerInParent="true"
android:background="#android:color/holo_green_light" />
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignStart="#id/customView"
android:layout_alignTop="#id/customView"
android:src="#drawable/circle"
android:translationX="-10dp"
android:translationY="-10dp" />
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignEnd="#id/customView"
android:layout_alignTop="#id/customView"
android:src="#drawable/circle"
android:translationX="10dp"
android:translationY="-10dp" />
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignBottom="#id/customView"
android:layout_alignStart="#id/customView"
android:src="#drawable/circle"
android:translationX="-10dp"
android:translationY="10dp" />
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignBottom="#id/customView"
android:layout_alignEnd="#id/customView"
android:src="#drawable/circle"
android:translationX="10dp"
android:translationY="10dp" />
</RelativeLayout>
circle.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<!-- fill color -->
<solid android:color="#android:color/holo_red_light" />
<size
android:width="20dp"
android:height="20dp" />
</shape>
The Actual Solution
Now that we have demonstrated that the mocked-up approach works, we now have to reproduce the effect in code. We will have to add the circle view and position it within the parent RelativeLayout using RelativeLayout view positioning and translations. The following code shows just the top left circle positioned, but the other circles will be positioned in a similar way.
activity_main.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Drawable circle = ContextCompat.getDrawable(this, R.drawable.circle);
ImageView imageView = new ImageView(this);
imageView.setImageDrawable(circle);
int circleSize = dpToPx(CIRCLE_SIZE_DP);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(circleSize, circleSize);
// Position top left circle within the custom view.
lp.addRule(RelativeLayout.ALIGN_START, R.id.customView);
lp.addRule(RelativeLayout.ALIGN_TOP, R.id.customView);
// Uncomment these 2 lines to position the top left circle with translation.
imageView.setTranslationX(-circleSize / 2);
imageView.setTranslationY(-circleSize / 2);
// Uncomment these 3 lines to position the top left circle with margins.
// View customView = findViewById(R.id.customView);
// lp.leftMargin = customView.getLeft() - circleSize / 2;
// lp.topMargin = customView.getTop() - circleSize / 2;
((RelativeLayout) findViewById(R.id.relativeLayout)).addView(imageView, lp);
}
private int dpToPx(int dp) {
return (int) (dp * getResources().getDisplayMetrics().density);
}
private static final int CIRCLE_SIZE_DP = 20;
}
The code above uses a shortened layout:
activity_main.xml
<RelativeLayout
android:id="#+id/relativeLayout"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:id="#+id/customView"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_centerInParent="true"
android:background="#android:color/holo_green_light" />
</RelativeLayout>
It is also possible to produce the same positioning using margins. The code to use margins is commented out but will work. (I think that negative margins may also work, but I have read that they are not officially supported, so I try to avoid them.)

GridLayout covering more than the screen size

Hello i am trying to make a design of chess board, I am using GridLayout containing buttons that corresponds to blocks of the boards. But the layout is so much bigger that it is not fitting the screen, how can i reduce the button size so that the layout fits the screen.
here is the code
public class BoardActivity extends AppCompatActivity {
private GridLayout mBoard;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_board);
mBoard = (GridLayout)findViewById(R.id.board_grid);
addItems();
}
public void addItems(){
int index = 0;
Button button;
for(int i = 0; i < 8; i++){
for(int j = 0; j < 8; j++){
button = new Button(this);
button.setId(index);
button.setPadding(0,0,0,0);
button.setText(""+index);
mBoard.addView(button);
index++;
}
}
}
}
and below is the xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context="com.example.harsh.chessgame.BoardActivity">
<GridLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:rowCount="8"
android:columnCount="8"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_marginBottom="0dp"
android:layout_marginTop="0dp"
android:id="#+id/board_grid">
</GridLayout>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/test_text"/>
</LinearLayout>
and the screenshot of the problem is below
Please help, sorry for mistakes and thanks for help.
In your code you have created Buttons programmatically and you haven't specified any width or height for them. You can add the below line in your code and the width and height will be adjusted.
button.setLayoutParams(new LinearLayout.LayoutParams(100, 100));
But for implementing a chess game, I you should better create a custom adapter for the gridview and images for black and white boxes should be inflated. Anyway for your current try this would help you.
Note: The width and height are just a random number currently given as 100.

Android - How to set margin to custom LinearLayouts in GridLayout?

I have problems with setting margin to a custom made linear layout class that I use multiple times in a GridLayout. The Gridlayout is placed in a fragment.
This is the code of fragment_grid.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="app_a_tize.expressme.Fragment.GridFragment"
android:layout_gravity="center">
<GridLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/orange"
android:layout_margin="5dp"
android:id="#+id/gridlayout_grid"></GridLayout>
</FrameLayout>
This is the code of the GridFragment.java:
public class GridFragment extends Fragment {
public GridFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_grid, container, false);
}
#Override
public void onStart() {
super.onStart();
GridLayout grid = (GridLayout) getView().findViewById(R.id.gridlayout_grid);
grid.setRowCount(3);
int tileHeight = (CategoryTileActivity.gridContentHeight -3 * 10) / 3;
int amountofColumns = (int) CategoryTileActivity.gridContentWidth / tileHeight;
grid.setColumnCount(amountofColumns);
grid.setMinimumWidth((amountofColumns * tileHeight) + (5 * 20 ));
for (int i = 0; i < 3 * amountofColumns; i++) {
//fill the grid with the custom LinearLayout:
grid.addView(new TileClass(getActivity(), tileHeight, tileHeight, "ToBeImplemented", "Button"));
}
}
}
This is the code of the custom LinearLayout:
public class TileClass extends LinearLayout {
public TileClass(Context context, int height, int width, String image, String text) {
super(context);
this.setBackgroundResource(R.drawable.tile_button); //creates rounded layouts
this.setMinimumHeight(height);
this.setMinimumWidth(width);
this.setOrientation(LinearLayout.VERTICAL);
ImageView tileImage = new ImageView(context);
Bitmap bMap = BitmapFactory.decodeResource(getResources(), R.drawable.tilephoto);
Bitmap bMapScaled = Bitmap.createScaledBitmap(bMap, 100, 100, true);
tileImage.setImageBitmap(bMapScaled);
tileImage.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
TextView tileText = new TextView(context);
tileText.setText(text);
tileText.setTextColor(Color.WHITE);
tileText.setGravity(Gravity.CENTER);
addView(tileImage);
addView(tileText);
}
}
When I run the Activity, I get this as result:
The code I showed above is responsible for the orange area in the middle. What I need: the blue "buttons"/LinearLayouts, in the orange area in the middle, to have a margin of 5dp. So the rest of the orange space is be taken by the custom LinearLayouts.
I don't know how to fix that, I tried a lot of options but they don't seem to work out for me.. Everything from MarginLayoutParams to params.setMargins(5,5,5,5); On almost every layout in my code.
I use Android Studio 2.1.2, supporting minimum of API 15.
Every help is appreciated!
For your imagination, this must be the end result, I need the margin like this:
You have to make custom view of gridview item as below:-
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="#dimen/categoryHeight"
android:layout_marginLeft="#dimen/margin_5dp"
android:layout_marginRight="#dimen/margin_5dp"
android:layout_marginTop="#dimen/margin_7dp"
android:background="#drawable/rounded_bg"
>
<ImageView
android:id="#+id/llRowItem"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scaleType="fitXY"
android:gravity="bottom"/>
<TextView
android:id="#+id/item_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/black_light"
android:padding="#dimen/margin_5dp"
android:layout_gravity="bottom"
android:singleLine="true"
android:textColor="#color/white"
android:textSize="#dimen/font_size_16sp" />
</FrameLayout>
and inside adapter set color of text view, background, text or image of imageview whatever you want to set.

How to fill imageview's background color like a progressbar?

I have a png image something like below and I need to fill its background color according to its capacity.
For example if tank has oil %100 percent of its capacity, background should be yellow , if has %25 , background should be %25 percent yellow and %75 transparent.
Assume that this is a healthbar in a game.
this is what i have in my layout, just a simple imageview in a linearlayout.
Is there any way to achieve this using animation, clip or something ?
<ImageView
android:id="#+id/ivOilTank"
android:layout_width="0dp"
android:src="#mipmap/oilTank"
android:layout_height="match_parent"
android:layout_weight="1">
Change your layout xml to contain-
<FrameLayout
android:layout_width="150dp"
android:layout_height="wrap_content"
android:background="#android:color/black"
>
<View
android:id="#+id/percent_highlight"
android:layout_width="0dp"
android:layout_height="match_parent"
/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#mipmap/oilTank"
/>
</FrameLayout>
Now wherever you want to highlight the certain percentage of the image -
View highlight = findViewById(R.id.percent_highlight);
highlight.setBackgroundResource(<Color_id>);//Any color you want to set
ViewGroup.LayoutParams layoutParams = highlight.getLayoutParams();
layoutParams.width = (int) (dpToPixel(150) * 25 / 100.0f);//If you want to set 25%
highlight.setLayoutParams(layoutParams);
where dpToPixel() converts dp to pixels -
public int dpToPixel(float dp) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
Here is my solution,
Since I am not interested in using dp for width property, i looked for another solution. If you want to use dp directly check Shadab Ansari's answer which gave me a clue.
frameLayout
<FrameLayout
android:id="#+id/flOil"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
>
<View
android:id="#+id/progress_view"
android:background="#fc12d108"
android:layout_width="55dp"
android:layout_height="match_parent"
android:layout_margin="1dp"/>
<ImageView
android:id="#+id/ivOil"
android:layout_width="match_parent"
android:src="#mipmap/oilTank"
android:layout_height="match_parent"
>
</ImageView>
</FrameLayout>
Code
ViewTreeObserver vto = ivRate.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
public boolean onPreDraw() {
ivRate.getViewTreeObserver().removeOnPreDrawListener(this);
widthTank = ivRate.getMeasuredWidth();//get the width of the imageView which has oilTank image as dp.
ViewGroup.LayoutParams layoutParams = prgrs.getLayoutParams();
layoutParams.width = (int) (widthTank / (new Random().nextInt(4) + 2));//calculate a width for view which is going to fill background color, random was user for testwill be using desired value.
prgrs.setLayoutParams(layoutParams);
return true;
}
});
Before using widthTank variable , onPreDraw method has to be called so be sure that it is called otherwise it will not be assigned.
Please checkout this example
https://github.com/fanrunqi/WaveProgressView or https://github.com/rathodchintan/Percentage-wise-Image-Filling
this is the best way to fill image

setPadding(0,0,0,0) called several times on View after constructor

Good evening! I'm trying to setPadding on a custom View i built and the native setPadding() did nothing so i wrote my own... After a while i realized that setPadding gets called several times after my original call and i have no idea why... Please help :) (I realize that my custom setPadding maybe quite excessive ^^)
Here is the XML containing the View. It's the PieChart.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/PieDialog_llParent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/PieDialog_tvHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Header"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/PieDialog_tvDiv1"
android:layout_width="match_parent"
android:layout_height="2dp"
android:textSize="0sp"/>
<TextView
android:id="#+id/PieDialog_tvDiv2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="0sp" />
<com.SverkerSbrg.Spendo.Statistics.Piechart.PieChart
android:id="#+id/PieDialog_Pie"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/PieDialog_tvDiv3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="0sp" />
<FrameLayout
android:id="#+id/PieDialog_flClose"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/PieDialog_tvClose"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Large Text" />
</FrameLayout>
</LinearLayout>
And here is the code where i use the xml:
package com.SverkerSbrg.Spendo.Transaction.TransactionList.PieDialog;
imports...
public class PieDialog extends SpendoDialog{
private TransactionSet transactionSet;
private TransactionGroup transactionGroup;
private GUI_attrs gui_attrs;
private PieData pieData;
private PieChart pie;
private TextView tvHeader;
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.transaction_list_pie_dialog, null);
LinearLayout llParent = (LinearLayout) view.findViewById(R.id.PieDialog_llParent);
llParent.setBackgroundColor(gui_attrs.color_Z0);
tvHeader = (TextView) view.findViewById(R.id.PieDialog_tvHeader);
tvHeader.setTextSize(gui_attrs.textSize_header);
TextView tvDiv1 = (TextView) view.findViewById(R.id.PieDialog_tvDiv1);
tvDiv1.setBackgroundColor(gui_attrs.color_Z2);
TextView tvDiv2 = (TextView) view.findViewById(R.id.PieDialog_tvDiv2);
tvDiv2.setPadding(0, gui_attrs.padding_Z0, 0, 0);
PieChart pie = (PieChart) view.findViewById(R.id.PieDialog_Pie);
pie.setPadding(40, 10, 40, 10);
builder.setView(view);
AlertDialog ad = builder.create();
return ad;
}
public void initialize(GUI_attrs gui_attrs, TransactionSet transactionSet, long groupIdentifier){
this.gui_attrs = gui_attrs;
this.transactionSet = transactionSet;
}
}
Just to extrapolate on my comment, it is your custom View object's responsibility to respect the padding that is set. You can do something like the following to make sure that you handle that case:
onMeasure()
int desiredWidth, desiredHeight;
desiredWidth = //Determine how much width you need
desiredWidth += getPaddingLeft() + getPaddingRight();
desiredHeight = //Determine how much height you need
desiredHeight += getPaddingTop() + getPaddingBottom();
int measuredHeight, measuredWidth;
//Check against the MeasureSpec -- if it's MeasureSpec.EXACTLY, or MeasureSpec.AT_MOST
//follow those restrictions to determine the measured dimension
setMeasuredDimension(measuredWidth, measuredHeight);
onLayout()
int leftOffset = getPaddingLeft();
int topOffset = getPaddingTop();
//layout your children (if any) according to the left and top offsets,
//rather than just 0, 0
onDraw()
canvas.translate (getPaddingLeft(), getPaddingTop());
//Now draw your stuff as normal

Categories

Resources