I have a "complex" layout that I want to "move" to a custom component to be able to re-utilize easily but when I do that ProgressBar disappears. I think that the cause could be that the ProgressBar has a custom progressDrawable.
During code execution, progress bar is accessible and visible (well I can't see it, but I check that the visibility property is not the problem...) and there are no errors.
My Custom Layout
...
</LinearLayout>
</LinearLayout>
<!-- Progressbar -->
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="match_parent"
>
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="5dp"
android:id="#+id/progressBar"
android:progressDrawable="#drawable/customprogressbar"
android:layout_gravity="center_horizontal"
/>
</LinearLayout>
</LinearLayout>
My Custom Layout class
public class CustomLayout extends LinearLayout {
public CustomLayout(Context context) {
super(context);
}
public CustomLayout(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.custom_layout, this, true);
}
}
My progressDrawable
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Define the background properties like color etc -->
<item android:id="#android:id/background">
<shape>
<gradient
android:startColor="#000001"
android:centerColor="#0b131e"
android:centerY="1.0"
android:endColor="#0d1522"
android:angle="270"
/>
</shape>
</item>
<!-- Define the progress properties like start color, end color etc -->
<item android:id="#android:id/progress">
<clip>
<shape>
<gradient
android:startColor="#007A00"
android:centerColor="#007A00"
android:centerY="1.0"
android:endColor="#06101d"
android:angle="270"
/>
</shape>
</clip>
</item>
</layer-list>
My Container Layout Main Activity
<?xml version="1.0" encoding="utf-8"?>
<my.custom.namespace xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent">
</my.custom.namespace>
My Main Activity
...
setContentView(R.layout.main_activity);
...
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
// Progress bar is get fine, and I checked that visibility is VISIBLE
// I didn't change a line of code of this after moving the layout to a custom control
String showProgressbar = sharedPrefs.getString("settings_progressbar_value", Constants.PROGRESSBAR_VISIBLE_BY_DEFAULT);
if (showProgressbar.equals(Constants.PROGRESSBAR_VISIBLE_BY_DEFAULT)) {
mProgressBar.setVisibility(View.VISIBLE);
} else {
mProgressBar.setVisibility(View.GONE);
}
Related
I'm trying to make my disabled EditText's style like in guidelines:
https://www.google.com/design/spec/components/text-fields.html#text-fields-labels
<EditText
android:id="#+id/account_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/test_account"
android:enabled="false" />
I've already implemented material design styles, so all my widgets look material.
The question is: Is there any way to get this dotted underline using styles, without putting additional views?
My styles.xml:
<style name="Theme.Main" parent="#style/Theme.AppCompat.Light.NoActionBar">
<item name="android:editTextStyle">#style/android:Widget.Material.EditText</item>
</style>
Finally I managed to do as you've shown, It looks like
Create dotted.xml inside drawable folder and paste these
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="1dp"
android:left="-2dp"
android:right="-2dp"
android:top="-2dp">
<shape android:shape="rectangle">
<stroke
android:width="0.5dp"
android:color="#android:color/black" />
<solid android:color="#ffffff" />
<stroke
android:width="1dp"
android:color="#030310"
android:dashGap="5dp"
android:dashWidth="5dp" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
</shape>
</item>
</layer-list>
Then simply set the android:background attribute to dotted.xml we just created. Your EditText looks like this.
<EditText
android:id="#+id/account_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test account"
android:background="#drawable/dotted"
style="#style/Theme.Main" <!--Its your custom style-->
android:enabled="false" />
AFAIK, there is no "stock" way. Take the material design guidelines as it is, a guideline ;)
Finally I ended up with a custom view. It might be not the most elegant solution but it solves my task.
Hope it will be helpful for someone.
DisabledTextField.java:
package com.kabunov.example.ui.common;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.kabunov.example.R;
public final class DisabledTextField extends FrameLayout {
private TextView tvCaption;
private TextView tvText;
private View divider;
public DisabledTextField(final Context context) {
this(context, null);
}
public DisabledTextField(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public DisabledTextField(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
View.inflate(getContext(), R.layout.component_disabled_text_field, this);
tvCaption = (TextView) findViewById(R.id.caption);
tvText = (TextView) findViewById(R.id.value);
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DisabledTextField);
if (null != typedArray) {
final String captionText = typedArray.getString(R.styleable.DisabledTextField_caption);
if (TextUtils.isEmpty(captionText)) {
tvCaption.setVisibility(GONE);
} else {
tvCaption.setText(captionText);
tvCaption.setVisibility(VISIBLE);
}
final String text = typedArray.getString(R.styleable.DisabledTextField_disabledText);
tvText.setText(text);
typedArray.recycle();
}
}
public final void setCaption(final CharSequence caption) {
this.tvCaption.setText(caption);
this.tvCaption.setVisibility(VISIBLE);
}
public final void setDisabledText(final CharSequence value) {
this.tvText.setText(value);
}
}
/layout/component_disabled_text.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">
<TextView
android:id="#+id/caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/DisabledTextFieldCaption"/>
<TextView
android:id="#+id/value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/DisabledTextFieldValue"/>
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#drawable/disabled_text_field_background"
android:layerType="software"/>
</LinearLayout>
/values/attributes_disabled_text_field.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DisabledTextField">
<attr name="caption" format="string"/>
<attr name="disabledText" format="string"/>
</declare-styleable>
</resources>
/drawable/disabled_text_field_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="-1dp"
android:left="-1dp"
android:right="-1dp"
android:top="0dp">
<shape android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#color/text_color_disabled_text_view"
android:dashGap="2dp"
android:dashWidth="1dp" />
<solid android:color="#android:color/transparent" />
</shape>
</item>
</layer-list>
/values/styles.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="text_color_disabled_text_view">#61000000</color>
<style name="DisabledTextFieldCaption">
<item name="android:textSize">12sp</item>
<item name="android:textColor">#color/text_color_disabled_text_view</item>
</style>
<style name="DisabledTextFieldValue">
<item name="android:layout_marginTop">3dp</item>
<item name="android:layout_marginBottom">8dp</item>
<item name="android:textSize">16sp</item>
<item name="android:textColor">#color/text_color_disabled_text_view</item>
</style>
</resources>
Example of usage:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.kabunov.example.ui.common.DisabledTextField
android:id="#+id/example"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:caption="Some caption"
custom:disabledText="Disabled text"/>
</LinearLayout>
And the result:
I am using RecyclerView with rounded corner, to make it rounded corner I used below XML:
view_rounded.xml:-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#008f8471"/>
<stroke android:width="2dp" android:color="#ffffff" />
<corners android:radius="10dp"/>
</shape>
fragment_main.xml:-
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/view_rounded"/>
adapter_main.xml:-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/textTitle"
style="#style/AppTheme.ListTextView"
/>
</LinearLayout>
style.xml:-
<style name="AppTheme.ListTextView" parent="android:Widget.Material.TextView">
<item name="android:gravity">left</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textAllCaps">false</item>
<item name="android:padding">10dp</item>
<item name="android:textAppearance">#android:style/TextAppearance.DeviceDefault.Medium</item>
<item name="android:textColor">#color/tabsScrollColor</item>
<item name="android:textStyle">bold</item>
</style>
Getting (without item separator):
Required (with item separator):
you should try add Divider
mListview.addItemDecoration(new DividerItemDecoration(this.getActivity(), LinearLayout.VERTICAL));
I have done this way:
onCreateView() of Fragment:
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
recyclerView.addItemDecoration(new SimpleDividerItemDecoration(getActivity()));
SimpleDividerItemDecoration.java:
public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration {
private Drawable mDivider;
public SimpleDividerItemDecoration(Context context) {
mDivider = context.getResources().getDrawable(R.drawable.recycler_horizontal_divider);
}
#Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int top = child.getBottom() + params.bottomMargin;
int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
recycler_horizontal_divider.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="1dp"
android:height="1dp" />
<solid android:color="#2EC590" />
</shape>
Hope this will help you.
RecyclerView works different from ListViews. You need to add ItemDecorators for the recycler view. As the docs says,
An ItemDecoration allows the application to add a special drawing and layout offset to specific item views from the adapter's data set. This can be useful for drawing dividers between items, highlights, visual grouping boundaries and more.
Take a look into this link : https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ItemDecoration.html
Well what I did to achieve this is, I first created layout for my adapter row as
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:id="#+id/lineView"
android:layout_width="match_parent"
android:layout_height="2px"
android:background="#android:color/black"/>
<TextView
android:id="#+id/textTitle"
style="#style/AppTheme.ListTextView"
/>
</LinearLayout>
Then in my adapter I checked for first row and changed its viewLine Visibility to invisible
#Override
public void onBindViewHolder(ChildInfoViewHolder holder, final int position) {
if(position == 0){
holder.viewLine.setVisibility(View.INVISIBLE);
}
//...
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
protected View viewLine;
public ChildInfoViewHolder(View view) {
super(view);
viewLine = view.findViewById(R.id.viewLine);
//...
}
}
To add dividers to your recyclerview you need to use decorator - https://gist.github.com/alexfu/0f464fc3742f134ccd1e after you add that to your project add a line
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
This line of code worked for me:
recyclerView.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.HORIZONTAL));
For vertical line, pass second argument as DividerItemDecoration.VERTICAL.
Set the selector at the background of the list item in your layout if you are using custom adapter
Try this one:
A very nice solution by Michel-F. Portzert
public class ClippedListView extends ListView {
public ClippedListView(Context context) {
super(context);
}
public ClippedListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void dispatchDraw(Canvas canvas) {
float radius = 10.0f;
Path clipPath = new Path();
RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight());
clipPath.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(clipPath);
super.dispatchDraw(canvas);
}
}
Try This From
Reference
Android: ListView with rounded corners
First off, we need the drawables for the backgrounds of the Lists entries:
For the entries in the middle of the list, we don't need rounded corners, so create a xml in your drawable folder "list_entry_middle.xml" with following content:
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<stroke android:width="1px" android:color="#ffbbbbbb" />
</shape>
</item>
<item android:bottom="1dp" android:left="1dp" android:right="1dp">
<shape >
<solid android:color="#ffffffff" />
</shape>
</item>
</layer-list>
For the rounded corners, create another xml, "rounded_corner_top.xml":
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<stroke android:width="1dp" android:color="#ffbbbbbb" />
<corners android:topLeftRadius="20dp"
android:topRightRadius="20dp"
/>
</shape>
</item>
<item android:top="1dp" android:left="1dp" android:right="1dp" android:bottom="1dp">
<shape >
<solid android:color="#ffffffff" />
<corners android:topLeftRadius="20dp"
android:topRightRadius="20dp"
/>
</shape>
</item>
</layer-list>
Implementing the bottom part is quite the same, just with bottomLeftRadius and bottomRightRadius. (maybe also create one with all corners rounded, if the list only has one entry)
For better usability, also provide drawables with other colors for the different states, that the list item can have and reference them in another xml in the drawable folder ("selector_rounded_corner_top.xml") as followed:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/rounded_corner_top_click"
android:state_pressed="true" />
<item android:drawable="#drawable/rounded_corner_top_click"
android:state_focused="true" />
<item android:drawable="#drawable/rounded_corner_top" />
</selector>
Now do the same for the other backgrounds of the list.
All that is left now, is to assign the right backgrounds in our ListAdapter like following:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//...
//skipping the view reuse stuff
if (position == 0 && entry_list.size() == 1) {
view.setBackgroundResource(R.drawable.selector_rounded_corner);
} else if (position == 0) {
view.setBackgroundResource(R.drawable.selector_rounded_corner_top);
} else if (position == entry_list.size() - 1) {
view.setBackgroundResource(R.drawable.selector_rounded_corner_bottom);
} else {
view.setBackgroundResource(R.drawable.selector_middle);
}
//...
//skipping the filling of the view
}
Modify your ListView like below.Add the list_bg as the background of your ListView Also specify some padding for the top and the bottom of the listView otherwise the 1st and the last item in the list will overlap with the rounded corners showing rectangular corners.
<ListView
android:id="#+id/listView"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="#drawable/list_bg"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:fastScrollEnabled="true"
android:choiceMode="singleChoice" />
Use this drawable xml for curve shape listview and set background to your list view or any layout:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="6dp" />
<padding android:bottom="3dp" android:left="3dp" android:right="3dp" android:top="3dp" />
</shape>
Try this
custom_rounded_list.xml :
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#ff2521"
android:endColor="#2f5511"
android:angle="270"/>
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
<corners
android:bottomRightRadius="7dp"
android:bottomLeftRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp" />
</shape>
Your listview:
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/mylst"
android:background="#drawable/custom_rounded_list" />
you are setting list_selector for both textview and listview background. Use list_selector only for listview and if you want hover effect on textview too, then create another list_selector_textview which haven't include the <corners android:radius="10dp" property.
The problem is because you are setting the background with corners not only to the list view, but also to the item. You should make separate backgrounds for item (with selector) and one for list view with corners.
list_bg.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#008f8471"/>
<stroke android:width="1dip" android:color="#ffffff" />
<corners android:radius="10dp"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>
Now you can setup this drawable as the background of your list view.
<ListView
android:id="#+id/listView"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="#drawable/list_bg.xml"
android:fastScrollEnabled="true"
android:choiceMode="singleChoice" />
And for list view item you can use selector to have hover functionality:
list_item_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/list_item_selected" android:state_pressed="true"/>
<item android:drawable="#drawable/list_item_selected" android:state_pressed="false" android:state_selected="true"/>
<item android:drawable="#android:color/transparent"/>
Where list_item_selected is :
list_item_selected.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4d8f8471"/>
<stroke android:width="1dip" android:color="#ffffff" />
</shape>
And after that you can setup this selector to the item in your xml:
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/list_item_selector" />
So your list view will have always same background with corners, and the background of items of list view, will be without corners and will be changed in pressed or selected state.
Just One Line...
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), null));
That's all
Try this
recyclerView.apply {
....
addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
}
Hi i have made a custom view and a lifebarprocess.xml . I want to draw the lifebar in my custom view with all the other things i draw. But i don't know how to:
-Creat/reference the processbar inside my view and how i can draw it.
-May change the progressbar xml ?
The custom view (shorted):
public class Gamecontroller_View extends View implements OnGestureListener{
private Paint mPaint;
public Gamecontroller_View(){
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
mPaint.setMaskFilter(new BlurMaskFilter(15, Blur.OUTER));
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (fingerpointer != null){
mPaint.setColor(colors[0]);
canvas.drawCircle(fingerpointer.x, fingerpointer.y, 30, mPaint);
}
//I want to draw a Progressbar's current appearance here
}
}
lifeprocessbar.xml:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="#android:id/background">
<shape>
<corners android:radius="5dip" />
<gradient
android:angle="270"
android:centerColor="#ff5a5d5a"
android:centerY="0.5"
android:endColor="#ff747674"
android:startColor="#ff9d9e9d" />
</shape>
</item>
<item android:id="#android:id/progress">
<clip>
<shape>
<corners android:radius="5dip" />
<gradient
android:angle="0"
android:endColor="#ff0000"
android:startColor="#ff3300" />
</shape>
</clip>
</item>
</layer-list>
there is also the lifebarprocess_layout:
<?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" >
<ProgressBar
android:id="#+id/playerlifeprocessbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginTop="30dp"
android:progress="90"
android:progressDrawable="#drawable/lifeprocessbar" />
</LinearLayout>
My someone can help - thanks in adavance.
You may want to consider extending ViewGroup in your Gamecontroller_View instead of View. From the documentation:
A ViewGroup is a special view that can contain other views (called
children.) The view group is the base class for layouts and views
containers.
I am working on an app in which I want to show a ProgressBar, but I want to replace the default Android ProgressBar.
So how can I customize the ProgressBar?
Do I need some graphics and animation for that?
I read the following post but could not get it to work:
Custom Progress bar Android
Customizing a ProgressBar requires defining the attribute or properties for the background and progress of your progress bar.
Create an XML file named customprogressbar.xml in your res->drawable folder:
custom_progressbar.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Define the background properties like color etc -->
<item android:id="#android:id/background">
<shape>
<gradient
android:startColor="#000001"
android:centerColor="#0b131e"
android:centerY="1.0"
android:endColor="#0d1522"
android:angle="270"
/>
</shape>
</item>
<!-- Define the progress properties like start color, end color etc -->
<item android:id="#android:id/progress">
<clip>
<shape>
<gradient
android:startColor="#007A00"
android:centerColor="#007A00"
android:centerY="1.0"
android:endColor="#06101d"
android:angle="270"
/>
</shape>
</clip>
</item>
</layer-list>
Now you need to set the progressDrawable property in customprogressbar.xml (drawable)
You can do this in the XML file or in the Activity (at run time).
Do the following in your XML:
<ProgressBar
android:id="#+id/progressBar1"
style="?android:attr/progressBarStyleHorizontal"
android:progressDrawable="#drawable/custom_progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
At run time do the following
// Get the Drawable custom_progressbar
Drawable draw=res.getDrawable(R.drawable.custom_progressbar);
// set the drawable as progress drawable
progressBar.setProgressDrawable(draw);
Edit: corrected xml layout
In case of complex ProgressBar like this,
use ClipDrawable.
NOTE : I've not used ProgressBar here in this example. I've achieved
this using ClipDrawable by clipping image with Animation.
A Drawable that clips another Drawable based on this Drawable's current level value. You can control how much the child Drawable gets clipped in width and height based on the level, as well as a gravity to control where it is placed in its overall container. Most often used to implement things like progress bars, by increasing the drawable's level with setLevel().
NOTE : The drawable is clipped completely and not visible when the level is 0
and fully revealed when the level is 10,000.
I've used this two images to make this CustomProgressBar.
scall.png
ballon_progress.png
MainActivity.java
public class MainActivity extends ActionBarActivity {
private EditText etPercent;
private ClipDrawable mImageDrawable;
// a field in your class
private int mLevel = 0;
private int fromLevel = 0;
private int toLevel = 0;
public static final int MAX_LEVEL = 10000;
public static final int LEVEL_DIFF = 100;
public static final int DELAY = 30;
private Handler mUpHandler = new Handler();
private Runnable animateUpImage = new Runnable() {
#Override
public void run() {
doTheUpAnimation(fromLevel, toLevel);
}
};
private Handler mDownHandler = new Handler();
private Runnable animateDownImage = new Runnable() {
#Override
public void run() {
doTheDownAnimation(fromLevel, toLevel);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etPercent = (EditText) findViewById(R.id.etPercent);
ImageView img = (ImageView) findViewById(R.id.imageView1);
mImageDrawable = (ClipDrawable) img.getDrawable();
mImageDrawable.setLevel(0);
}
private void doTheUpAnimation(int fromLevel, int toLevel) {
mLevel += LEVEL_DIFF;
mImageDrawable.setLevel(mLevel);
if (mLevel <= toLevel) {
mUpHandler.postDelayed(animateUpImage, DELAY);
} else {
mUpHandler.removeCallbacks(animateUpImage);
MainActivity.this.fromLevel = toLevel;
}
}
private void doTheDownAnimation(int fromLevel, int toLevel) {
mLevel -= LEVEL_DIFF;
mImageDrawable.setLevel(mLevel);
if (mLevel >= toLevel) {
mDownHandler.postDelayed(animateDownImage, DELAY);
} else {
mDownHandler.removeCallbacks(animateDownImage);
MainActivity.this.fromLevel = toLevel;
}
}
public void onClickOk(View v) {
int temp_level = ((Integer.parseInt(etPercent.getText().toString())) * MAX_LEVEL) / 100;
if (toLevel == temp_level || temp_level > MAX_LEVEL) {
return;
}
toLevel = (temp_level <= MAX_LEVEL) ? temp_level : toLevel;
if (toLevel > fromLevel) {
// cancel previous process first
mDownHandler.removeCallbacks(animateDownImage);
MainActivity.this.fromLevel = toLevel;
mUpHandler.post(animateUpImage);
} else {
// cancel previous process first
mUpHandler.removeCallbacks(animateUpImage);
MainActivity.this.fromLevel = toLevel;
mDownHandler.post(animateDownImage);
}
}
}
activity_main.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="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="#+id/etPercent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="number"
android:maxLength="3" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Ok"
android:onClick="onClickOk" />
</LinearLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<ImageView
android:id="#+id/imageView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/scall" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/clip_source" />
</FrameLayout>
clip_source.xml
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="vertical"
android:drawable="#drawable/ballon_progress"
android:gravity="bottom" />
In case of complex HorizontalProgressBar just change cliporientation in clip_source.xml like this,
android:clipOrientation="horizontal"
You can download complete demo from here.
in your xml
<ProgressBar
android:id="#+id/progressBar1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="#style/CustomProgressBar"
android:layout_margin="5dip" />
And in res/values/styles.xml:
<resources>
<style name="CustomProgressBar" parent="android:Widget.ProgressBar.Horizontal">
<item name="android:indeterminateOnly">false</item>
<item name="android:progressDrawable">#drawable/custom_progress_bar_horizontal</item>
<item name="android:minHeight">10dip</item>
<item name="android:maxHeight">20dip</item>
</style>
<style name="AppTheme" parent="android:Theme.Light" />
</resources>
And custom_progress_bar_horizontal is a xml stored in drawable folder which defines your custom progress bar. For more detail see this blog.
I hope this will help you.
There are two types of progress bars called determinate progress bar (fixed duration) and indeterminate progress bar (unknown duration).
Drawables for both of types of progress bar can be customized by defining drawable as xml resource. You can find more information about progress bar styles and customization at http://www.zoftino.com/android-progressbar-and-custom-progressbar-examples.
Customizing fixed or horizontal progress bar :
Below xml is a drawable resource for horizontal progress bar customization.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background"
android:gravity="center_vertical|fill_horizontal">
<shape android:shape="rectangle"
android:tint="?attr/colorControlNormal">
<corners android:radius="8dp"/>
<size android:height="20dp" />
<solid android:color="#90caf9" />
</shape>
</item>
<item android:id="#android:id/progress"
android:gravity="center_vertical|fill_horizontal">
<scale android:scaleWidth="100%">
<shape android:shape="rectangle"
android:tint="?attr/colorControlActivated">
<corners android:radius="8dp"/>
<size android:height="20dp" />
<solid android:color="#b9f6ca" />
</shape>
</scale>
</item>
</layer-list>
Customizing indeterminate progress bar
Below xml is a drawable resource for circular progress bar customization.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/progress"
android:top="16dp"
android:bottom="16dp">
<rotate
android:fromDegrees="45"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="315">
<shape android:shape="rectangle">
<size
android:width="80dp"
android:height="80dp" />
<stroke
android:width="6dp"
android:color="#b71c1c" />
</shape>
</rotate>
</item>
</layer-list>
Customizing the color of progressbar namely in case of spinner type needs an xml file and initiating codes in their respective java files.
Create an xml file and name it as progressbar.xml
<?xml version="1.0" encoding="utf-8"?>
<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:gravity="center"
tools:context=".Radio_Activity" >
<LinearLayout
android:id="#+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ProgressBar
android:id="#+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</ProgressBar>
</LinearLayout>
</LinearLayout>
Use the following code to get the spinner in various expected color.Here we use the hexcode to display spinner in blue color.
Progressbar spinner = (ProgressBar) progrees.findViewById(R.id.spinner);
spinner.getIndeterminateDrawable().setColorFilter(Color.parseColor("#80DAEB"),
android.graphics.PorterDuff.Mode.MULTIPLY);
For using custom drawable:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:drawable="#drawable/my_drawable"
android:pivotX="50%"
android:pivotY="50%" />
(add under res/drawable progress.xml). my_drawable may be xml, png
Then in your layout use
<ProgressBar
android:id="#+id/progressBar"
android:indeterminateDrawable="#drawable/progress_circle"
...
/>
Creating Custom ProgressBar like hotstar.
Add Progress bar on layout file and set the indeterminateDrawable with drawable file.
activity_main.xml
<ProgressBar
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:id="#+id/player_progressbar"
android:indeterminateDrawable="#drawable/custom_progress_bar"
/>
Create new xml file in res\drawable
custom_progress_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="1080" >
<shape
android:innerRadius="35dp"
android:shape="ring"
android:thickness="3dp"
android:useLevel="false" >
<size
android:height="80dp"
android:width="80dp" />
<gradient
android:centerColor="#80b7b4b2"
android:centerY="0.5"
android:endColor="#f4eef0"
android:startColor="#00938c87"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
Simplest way to create customize a progress bar in Android:
Initialize and show dialog:
MyProgressDialog progressdialog = new MyProgressDialog(getActivity());
progressdialog.show();
Create method:
public class MyProgressDialog extends AlertDialog {
public MyProgressDialog(Context context) {
super(context);
getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
}
#Override
public void show() {
super.show();
setContentView(R.layout.dialog_progress);
}
}
Create layout XML:
<RelativeLayout 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"
android:background="#android:color/transparent"
android:clickable="true">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<ProgressBar
android:id="#+id/progressbarr"
android:layout_width="#dimen/eightfive"
android:layout_height="#dimen/eightfive"
android:layout_centerInParent="true"
android:indeterminateDrawable="#drawable/progresscustombg" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#+id/progressbarr"
android:layout_marginTop="#dimen/_3sdp"
android:textColor="#color/white"
android:text="Please wait"/>
</RelativeLayout>
</RelativeLayout>
Create shape progresscustombg.xml and put res/drawable:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" >
<shape
android:innerRadiusRatio="3"
android:shape="ring"
android:thicknessRatio="20"
android:useLevel="false" >
<size
android:height="#dimen/eightfive"
android:width="#dimen/eightfive" />
<gradient
android:centerY="0.50"
android:endColor="#color/color_green_icash"
android:startColor="#FFFFFF"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
If you want to do this in code, here is a sample:
pd = new ProgressDialog(MainActivity.this);
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pd.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
pd.getWindow().setGravity(Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL);
TextView tv = new TextView(this);
tv.setTextColor(Color.WHITE);
tv.setTextSize(20);
tv.setText("Waiting...");
pd.setCustomTitle(tv);
pd.setIndeterminate(true);
pd.show();
Using TextView gives you an option to change color, size, and font of your text. Otherwise you can just call setMessage(), as usual.
<ProgressBar
android:indeterminateDrawable="#drawable/loading"
style="?android:attr/progressBarStyleLarge"
android:layout_gravity="center"
android:layout_width="200dp"
android:layout_height="200dp"
android:scaleY="0.5"
android:scaleX="0.5"
android:id="#+id/progressBarGallery"/>
and #drawable/loading is src\main\res\drawable\loading.gif file, and its size is 200 by 200
So I have a ListView and I want to change the color of each items background and text. This ListView is inside a ListFragment. My code inflates the layout in the onCreateView and inflates the layout of each item in the newView.
The android:state_pressed="true" is working fine, whenever I press in one item the background changes to that color. But when selecting an item neither the bg color or text color changes, even though I've defined an item with android:state_selected="true" in the selector.
Edit: I'm using SDK level 11 (Android 3.0) and a Motorola Xoom.
The list fragment layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
The list item layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="25dp"
android:background="#drawable/list_item_bg_selector">
<TextView android:id="#+id/form_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="#dimen/text_size_xlarge"
android:textStyle="bold"
android:textColor="#drawable/list_item_text_selector" />
<TextView android:id="#+id/form_subtitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="#dimen/text_size_medium"
android:textStyle="normal"
android:layout_marginTop="5dp"
android:textColor="#drawable/list_item_text_selector" />
</LinearLayout>
The background selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="#color/white" />
<item
android:state_selected="true"
android:drawable="#drawable/list_item_bg_selected" />
<item
android:drawable="#color/list_bg" />
</selector>
The text selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="true"
android:drawable="#color/white" />
<item
android:drawable="#color/list_text_blue" />
</selector>
The answer is to use the android:state_activated="true" state, instead of the "selected" state. More on this here: ListFragment Item Selected Background
The best solution with support of all API levels is to implement Checkable feature for list item View which means that the top view of your list item layout has to implement Checkable interface (in my case it was TextView, but the same can be applied on ViewGroup classes like LinearLayout). When you click on a list item, the ListView call setChecked method and there we change the state of View to use android:state_checked="true" selector. Together with list view android:choiceMode="singleChoice" it will select only one item.
The trick is to override onCreateDrawableState method and set the checked state here for drawables. See example of SelectableTextView bellow. After the setChecked is called, the checked state is stored and called refreshDrawableState.
Example of SelectableTextView:
package com.example.widget.SelectableTextView;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.Checkable;
import android.widget.TextView;
public class SelectableTextView extends TextView implements Checkable {
private static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
};
private boolean mChecked;
public SelectableTextView(Context context) {
super(context);
}
public SelectableTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SelectableTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SelectableTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
}
}
#Override
public boolean isChecked() {
return mChecked;
}
#Override
public void toggle() {
setSelected(!mChecked);
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
}
Example of selectable_list_item.xml layout:
<?xml version="1.0" encoding="utf-8"?>
<com.example.widget.SelectableTextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#color/list_item_selector_foreground"
android:background="#drawable/list_item_selector_background"
tools:text="Item 1"/>
Example of list_item_selector_foreground.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- checked -->
<item android:color="#color/list_item_text_active" android:state_checked="true"/>
<item android:color="#color/list_item_text"/>
</selector>
Example of list_item_selector_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/list_item_background_selected" android:state_pressed="true"/>
<item android:drawable="#color/list_item_background_selected" android:state_focused="true"/>
<item android:drawable="#color/list_item_background_active" android:state_checked="true"/>
<item android:drawable="#color/list_item_background"/>
</selector>
Do not forget to set clickable="true" for the layout. This solved my problem.
List item layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/list_item_bg_selector"
android:clickable="true" >
<TextView
android:id="#+id/tvNewsPreviewTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="3"
android:ellipsize="end"
android:textSize="#dimen/news_preview_title_textsize"
android:textStyle="bold" />
</RelativeLayout>
Background selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#color/black" />
<gradient android:startColor="#color/white" android:endColor="#color/white" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#color/holo_gray_darker" />
<gradient android:startColor="#color/holo_gray_bright" android:endColor="#color/holo_gray_bright" />
</shape>
</item>
</selector>
#Andrew S: Along with using activated state in selector , activated state must be set to false for default case as shown in below selector code.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false"
android:state_activated="false"
android:color="#color/dark_text_blue"/>
<item android:state_pressed="true"
android:color="#color/red"/>
<item android:state_activated="true"
android:color="#color/red"/>
</selector>