Is there a android standard badge or method to show action bar notification icon with a count like on Google examples?
If not, then what is the best way to make it?
I'm new to android, please help.
I am not sure if this is the best solution or not, but it is what I need.
Please tell me if you know what is need to be changed for better performance or quality. In my case, I have a button.
Custom item on my menu - main.xml
<item
android:id="#+id/badge"
android:actionLayout="#layout/feed_update_count"
android:icon="#drawable/shape_notification"
android:showAsAction="always">
</item>
Custom shape drawable (background square) - shape_notification.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:color="#22000000" android:width="2dp"/>
<corners android:radius="5dp" />
<solid android:color="#CC0001"/>
</shape>
Layout for my view - feed_update_count.xml
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/notif_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="32dp"
android:minHeight="32dp"
android:background="#drawable/shape_notification"
android:text="0"
android:textSize="16sp"
android:textColor="#android:color/white"
android:gravity="center"
android:padding="2dp"
android:singleLine="true">
</Button>
MainActivity - setting and updating my view
static Button notifCount;
static int mNotifCount = 0;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.main, menu);
View count = menu.findItem(R.id.badge).getActionView();
notifCount = (Button) count.findViewById(R.id.notif_count);
notifCount.setText(String.valueOf(mNotifCount));
return super.onCreateOptionsMenu(menu);
}
private void setNotifCount(int count){
mNotifCount = count;
invalidateOptionsMenu();
}
Edit Since version 26 of the support library (or androidx) you no longer need to implement a custom OnLongClickListener to display the tooltip. Simply call this:
TooltipCompat.setTooltipText(menu_hotlist, getString(R.string.hint_show_hot_message));
I'll just share my code in case someone wants something like this:
layout/menu/menu_actionbar.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
...
<item android:id="#+id/menu_hotlist"
android:actionLayout="#layout/action_bar_notifitcation_icon"
android:showAsAction="always"
android:icon="#drawable/ic_bell"
android:title="#string/hotlist" />
...
</menu>
layout/action_bar_notifitcation_icon.xml
Note style and android:clickable properties. these make the layout the size of a button and make the background gray when touched.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_gravity="center"
android:clickable="true"
style="#android:style/Widget.ActionButton">
<ImageView
android:id="#+id/hotlist_bell"
android:src="#drawable/ic_bell"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_margin="0dp"
android:contentDescription="bell"
/>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/hotlist_hot"
android:layout_width="wrap_content"
android:minWidth="17sp"
android:textSize="12sp"
android:textColor="#ffffffff"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#null"
android:layout_alignTop="#id/hotlist_bell"
android:layout_alignRight="#id/hotlist_bell"
android:layout_marginRight="0dp"
android:layout_marginTop="3dp"
android:paddingBottom="1dp"
android:paddingRight="4dp"
android:paddingLeft="4dp"
android:background="#drawable/rounded_square"/>
</RelativeLayout>
drawable-xhdpi/ic_bell.png
A 64x64 pixel image with 10 pixel wide paddings from all sides. You are supposed to have 8 pixel wide paddings, but I find most default items being slightly smaller than that. Of course, you'll want to use different sizes for different densities.
drawable/rounded_square.xml
Here, #ff222222 (color #222222 with alpha #ff (fully visible)) is the background color of my Action Bar.
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="2dp" />
<solid android:color="#ffff0000" />
<stroke android:color="#ff222222" android:width="2dp"/>
</shape>
com/ubergeek42/WeechatAndroid/WeechatActivity.java
Here we make it clickable and updatable! I created an abstract listener that provides Toast creation on onLongClick, the code was taken from from the sources of ActionBarSherlock.
private int hot_number = 0;
private TextView ui_hot = null;
#Override public boolean onCreateOptionsMenu(final Menu menu) {
MenuInflater menuInflater = getSupportMenuInflater();
menuInflater.inflate(R.menu.menu_actionbar, menu);
final View menu_hotlist = menu.findItem(R.id.menu_hotlist).getActionView();
ui_hot = (TextView) menu_hotlist.findViewById(R.id.hotlist_hot);
updateHotCount(hot_number);
new MyMenuItemStuffListener(menu_hotlist, "Show hot message") {
#Override
public void onClick(View v) {
onHotlistSelected();
}
};
return super.onCreateOptionsMenu(menu);
}
// call the updating code on the main thread,
// so we can call this asynchronously
public void updateHotCount(final int new_hot_number) {
hot_number = new_hot_number;
if (ui_hot == null) return;
runOnUiThread(new Runnable() {
#Override
public void run() {
if (new_hot_number == 0)
ui_hot.setVisibility(View.INVISIBLE);
else {
ui_hot.setVisibility(View.VISIBLE);
ui_hot.setText(Integer.toString(new_hot_number));
}
}
});
}
static abstract class MyMenuItemStuffListener implements View.OnClickListener, View.OnLongClickListener {
private String hint;
private View view;
MyMenuItemStuffListener(View view, String hint) {
this.view = view;
this.hint = hint;
view.setOnClickListener(this);
view.setOnLongClickListener(this);
}
#Override abstract public void onClick(View v);
#Override public boolean onLongClick(View v) {
final int[] screenPos = new int[2];
final Rect displayFrame = new Rect();
view.getLocationOnScreen(screenPos);
view.getWindowVisibleDisplayFrame(displayFrame);
final Context context = view.getContext();
final int width = view.getWidth();
final int height = view.getHeight();
final int midy = screenPos[1] + height / 2;
final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
Toast cheatSheet = Toast.makeText(context, hint, Toast.LENGTH_SHORT);
if (midy < displayFrame.height()) {
cheatSheet.setGravity(Gravity.TOP | Gravity.RIGHT,
screenWidth - screenPos[0] - width / 2, height);
} else {
cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
}
cheatSheet.show();
return true;
}
}
Just to add. If someone wants to implement a filled circle bubble, heres the code (name it bage_circle.xml):
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:useLevel="false"
android:thickness="9dp"
android:innerRadius="0dp"
>
<solid
android:color="#F00"
/>
<stroke
android:width="1dip"
android:color="#FFF" />
<padding
android:top="2dp"
android:bottom="2dp"/>
</shape>
You may have to adjust the thickness according to your need.
EDIT:
Here's the layout for button (name it badge_layout.xml):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.joanzapata.iconify.widget.IconButton
android:layout_width="44dp"
android:layout_height="44dp"
android:textSize="24sp"
android:textColor="#color/white"
android:background="#drawable/action_bar_icon_bg"
android:id="#+id/badge_icon_button"/>
<TextView
android:id="#+id/badge_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#id/badge_icon_button"
android:layout_alignRight="#id/badge_icon_button"
android:layout_alignEnd="#id/badge_icon_button"
android:text="10"
android:paddingEnd="8dp"
android:paddingRight="8dp"
android:paddingLeft="8dp"
android:gravity="center"
android:textColor="#FFF"
android:textSize="11sp"
android:background="#drawable/badge_circle"/>
</RelativeLayout>
In Menu create item:
<item
android:id="#+id/menu_messages"
android:showAsAction="always"
android:actionLayout="#layout/badge_layout"/>
In onCreateOptionsMenu get reference to the Menu item:
itemMessages = menu.findItem(R.id.menu_messages);
badgeLayout = (RelativeLayout) itemMessages.getActionView();
itemMessagesBadgeTextView = (TextView) badgeLayout.findViewById(R.id.badge_textView);
itemMessagesBadgeTextView.setVisibility(View.GONE); // initially hidden
iconButtonMessages = (IconButton) badgeLayout.findViewById(R.id.badge_icon_button);
iconButtonMessages.setText("{fa-envelope}");
iconButtonMessages.setTextColor(getResources().getColor(R.color.action_bar_icon_color_disabled));
iconButtonMessages.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (HJSession.getSession().getSessionId() != null) {
Intent intent = new Intent(getThis(), HJActivityMessagesContexts.class);
startActivityForResult(intent, HJRequestCodes.kHJRequestCodeActivityMessages.ordinal());
} else {
showLoginActivity();
}
}
});
After receiving notification for messages, set the count:
itemMessagesBadgeTextView.setText("" + count);
itemMessagesBadgeTextView.setVisibility(View.VISIBLE);
iconButtonMessages.setTextColor(getResources().getColor(R.color.white));
This code uses Iconify-fontawesome.
compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.+'
I don't like ActionView based solutions,
my idea is:
create a layout with TextView, that TextView will be populated by
application
when you need to draw a MenuItem:
2.1. inflate layout
2.2. call measure() & layout() (otherwise view will be 0px x 0px, it's too small for most use cases)
2.3. set the TextView's text
2.4. make "screenshot" of the view
2.6. set MenuItem's icon based on bitmap created on 2.4
profit!
so, result should be something like
create layout
here is a simple example
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/counterPanel"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="#drawable/ic_menu_gallery">
<RelativeLayout
android:id="#+id/counterValuePanel"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/counterBackground"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/unread_background" />
<TextView
android:id="#+id/count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"
android:textSize="8sp"
android:layout_centerInParent="true"
android:textColor="#FFFFFF" />
</RelativeLayout>
</FrameLayout>
#drawable/unread_background is that green TextView's background,
#drawable/ic_menu_gallery is not really required here, it's just to preview layout's result in IDE.
add code into onCreateOptionsMenu/onPrepareOptionsMenu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem menuItem = menu.findItem(R.id.testAction);
menuItem.setIcon(buildCounterDrawable(count, R.drawable.ic_menu_gallery));
return true;
}
Implement build-the-icon method:
private Drawable buildCounterDrawable(int count, int backgroundImageId) {
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.counter_menuitem_layout, null);
view.setBackgroundResource(backgroundImageId);
if (count == 0) {
View counterTextPanel = view.findViewById(R.id.counterValuePanel);
counterTextPanel.setVisibility(View.GONE);
} else {
TextView textView = (TextView) view.findViewById(R.id.count);
textView.setText("" + count);
}
view.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.setDrawingCacheEnabled(true);
view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
return new BitmapDrawable(getResources(), bitmap);
}
The complete code is here: https://github.com/cvoronin/ActionBarMenuItemCounter
Ok, for #AndrewS solution to work with v7 appCompat library:
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:someNamespace="http://schemas.android.com/apk/res-auto" >
<item
android:id="#+id/saved_badge"
someNamespace:showAsAction="always"
android:icon="#drawable/shape_notification" />
</menu>
.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.main, menu);
MenuItem item = menu.findItem(R.id.saved_badge);
MenuItemCompat.setActionView(item, R.layout.feed_update_count);
View view = MenuItemCompat.getActionView(item);
notifCount = (Button)view.findViewById(R.id.notif_count);
notifCount.setText(String.valueOf(mNotifCount));
}
private void setNotifCount(int count){
mNotifCount = count;
supportInvalidateOptionsMenu();
}
The rest of the code is the same.
Try looking at the answers to these questions, particularly the second one which has sample code:
How to implement dynamic values on menu item in Android
How to get text on an ActionBar Icon?
From what I see, You'll need to create your own custom ActionView implementation. An alternative might be a custom Drawable. Note that there appears to be no native implementation of a notification count for the Action Bar.
EDIT: The answer you were looking for, with code: Custom Notification View with sample implementation
When you use toolbar:
....
private void InitToolbar() {
toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
toolbartitle = (TextView) findViewById(R.id.titletool);
toolbar.inflateMenu(R.menu.show_post);
toolbar.setOnMenuItemClickListener(this);
Menu menu = toolbar.getMenu();
MenuItem menu_comments = menu.findItem(R.id.action_comments);
MenuItemCompat
.setActionView(menu_comments, R.layout.menu_commentscount);
View v = MenuItemCompat.getActionView(menu_comments);
v.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// Your Action
}
});
comment_count = (TextView) v.findViewById(R.id.count);
}
and in your load data call refreshMenu():
private void refreshMenu() {
comment_count.setVisibility(View.VISIBLE);
comment_count.setText("" + post_data.getComment_count());
}
I found a very good solution here, I'm using it with kotlin.
First, in the drawable folder you have to create item_count.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="8dp" />
<solid android:color="#f20000" />
<stroke
android:width="2dip"
android:color="#FFF" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
</shape>
In your Activity_Main Layout some like:
<RelativeLayout
android:id="#+id/badgeLayout"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_toRightOf="#+id/badge_layout1"
android:layout_gravity="end|center_vertical"
android:layout_marginEnd="5dp">
<RelativeLayout
android:id="#+id/relative_layout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="#+id/btnBadge"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#mipmap/ic_notification" />
</RelativeLayout>
<TextView
android:id="#+id/txtBadge"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_alignRight="#id/relative_layout1"
android:background="#drawable/item_count"
android:text="22"
android:textColor="#FFF"
android:textSize="7sp"
android:textStyle="bold"
android:gravity="center"/>
</RelativeLayout>
And you can modify like:
btnBadge.setOnClickListener { view ->
Snackbar.make(view,"badge click", Snackbar.LENGTH_LONG) .setAction("Action", null).show()
txtBadge.text = "0"
}
I found better way to do it.
if you want to use something like this
Use this dependency
compile 'com.nex3z:notification-badge:0.1.0'
create one xml file in drawable and Save it as Badge.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="#66000000"/>
<size android:width="30dp" android:height="40dp"/>
</shape>
</item>
<item android:bottom="1dp" android:right="0.6dp">
<shape android:shape="oval">
<solid android:color="#color/Error_color"/>
<size android:width="20dp" android:height="20dp"/>
</shape>
</item>
</layer-list>
Now wherever you want to use that badge use following code in xml.
with the help of this you will be able to see that badge on top-right corner of your image or anything.
<com.nex3z.notificationbadge.NotificationBadge
android:id="#+id/badge"
android:layout_toRightOf="#id/Your_ICON/IMAGE"
android:layout_alignTop="#id/Your_ICON/IMAGE"
android:layout_marginLeft="-16dp"
android:layout_marginTop="-8dp"
android:layout_width="28dp"
android:layout_height="28dp"
app:badgeBackground="#drawable/Badge"
app:maxTextLength="2"
></com.nex3z.notificationbadge.NotificationBadge>
Now finally on yourFile.java use this 2 simple thing..
1) Define
NotificationBadge mBadge;
2) where your loop or anything which is counting this number use this:
mBadge.setNumber(your_LoopCount);
here, mBadge.setNumber(0) will not show anything.
Hope this help.
Related
I'm working on a progress bar that shows the rating of a game.
Here an example CorrectGameRatingProgressBar.
Here's the code
ProgressBar userRatingProgressBar = root.findViewById(R.id.users_rating);
userRatingProgressBar.setProgress(0);
...
// game ratings
if (game.getRatingCount() > 0) {
userRatingProgressBar.setProgress((int) game.getRating());
gameUsersRatingText.setText(String.valueOf((int) game.getRating()));
} else {
userRatingProgressBar.setProgress(0);
gameUsersRatingText.setText("N/A");
}
...
It works well except for a thing: sometimes seems that setProgress(0) doesn't update the progress bar when I switch from a game to another that doesn't have a rating as shown here IncorrectGameRatingProgressBar. I even tried to set the progress bar to 0 before the "null check" but this thing happens anyway.
I tried this on a Xiaomi Mi9T with MIUI 12.0.5 (Android 10 QKQ1.190825.002) and on the Pixel 2 emulated on Android Studio with Android 11
Is there a way to fix this problem? If you need more infos, don't bother asking!
Thank you for all
I leave you down here the layout layout.xml of the activity
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:id="#+id/user_rating_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/GameDetailTextColor"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#+id/users_rating"
app:layout_constraintEnd_toEndOf="#+id/users_rating"
app:layout_constraintStart_toStartOf="#+id/users_rating"
app:layout_constraintTop_toTopOf="#+id/users_rating"
tools:text="60" />
<ProgressBar
android:id="#+id/users_rating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:indeterminateOnly="false"
android:progressDrawable="#drawable/rating_circle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:progress="60" />
</androidx.constraintlayout.widget.ConstraintLayout>
and the drawable custom_progress_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:shape="ring"
android:thicknessRatio="16"
android:useLevel="false">
<solid android:color="?attr/SearchBarBackgroundColor" />
</shape>
</item>
<item>
<rotate
android:fromDegrees="270"
android:toDegrees="270">
<shape
android:innerRadiusRatio="3.1"
android:shape="ring"
android:thicknessRatio="12"
android:useLevel="true">
<solid android:color="#color/orange_700" />
</shape>
</rotate>
</item>
</layer-list>
EDIT:
here's the code of the java fragment:
public class GameDetailFragment extends Fragment {
...
private long gameId = 0;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_game_detail, container, false);
if (getArguments() != null) {
gameId = getArguments().getLong("GAME_ID");
}
GameDetailViewModelFactory viewModelFactory = ((MainActivity) requireActivity()).getAppContainer().gameDetailViewModelFactory;
mViewModel = new ViewModelProvider(this, viewModelFactory).get(GameDetailViewModel.class);
...
ProgressBar userRatingProgressBar = root.findViewById(R.id.users_rating);
userRatingProgressBar.setProgress(0);
if (gameId != 0) {
...
// game ratings
if (game.getRatingCount() > 0) {
userRatingProgressBar.setProgress((int) game.getRating());
gameUsersRatingText.setText(String.valueOf((int) game.getRating()));
} else {
userRatingProgressBar.setProgress(0);
gameUsersRatingText.setText("N/A");
}
...
return root;
}
}
I find a solution!
Apparently I didn't set up the progress bar into the layout.xml
So, if you add android:progress="1" in the xml, the progress bar is getting updated everytime.
I have a custom seekbar with drawable and it is working fine, i am trying to make tooltip text on user action over the seekbar, is there any way without using third party library, i have posted the code below which i am using for custom seekbar
i have also attached a sample progress tooltip that i would like to achieve below
any reference or solution would be appreciated
implementation "com.android.support:appcompat-v7:${android_support_version}"
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progressValue, boolean fromUser) {
seekBar.setThumb(getThumb(progressValue));
TooltipCompat.setTooltipText(seekBar, String.valueOf(progressValue));
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
//Do nothing
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
//Do nothing
}
});
private Drawable getThumb(int progress) {
View thumbView = LayoutInflater.from(getActivity()).inflate(R.layout.seekbar_tv, null, false);
((TextView) thumbView.findViewById(R.id.tvProgress)).setText(progress + "");
thumbView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
Bitmap bitmap = Bitmap.createBitmap(thumbView.getMeasuredWidth(), thumbView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
thumbView.layout(0, 0, thumbView.getMeasuredWidth(), thumbView.getMeasuredHeight());
thumbView.draw(canvas);
return new BitmapDrawable(getResources(), bitmap);
}
<!--mySeekBarInLayout-->
<SeekBar
android:id="#+id/seekBar_Experience"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="10"
android:progressDrawable="#drawable/survey_seekbar_style"
android:splitTrack="false"
android:thumb="#drawable/survey_seekbar_thum" />
<!--survey_seekbar_thum-->
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="#color/circle_yellow"/>
<size
android:width="30dp"
android:height="30dp"/>
</shape>
</item>
</layer-list>
<!--survey_seekbar_style-->
<?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:drawable="#drawable/survey_border_shadow"
android:height="1dp"
android:gravity="center">
</item>
<item
android:id="#android:id/progress"
android:height="4dp"
android:gravity="center">
<clip android:drawable="#drawable/survey_seekbar_progress" />
</item>
</layer-list>
<!--survey_border_shadow-->
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:endColor="#color/thr_dark_blue"
android:startColor="#color/thr_dark_blue" />
</shape>
</item>
</layer-list>
<!--survey_seekbar_progress-->
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/progressshape" >
<clip>
<shape
android:shape="rectangle" >
<size android:height="3dp"/>
<corners
android:radius="5dp" />
<solid android:color="#color/thr_dark_blue"/>
</shape>
</clip>
</item>
</layer-list>
You should have your customized textview and change the text inside onProgressChanged.
Is that enough? ==> No
You need to change the x coordinate of the textview to change it's place to be compatible with seekbar place.
Code demonstrate that:
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
yourTextView.setText(progress + " miles");
// Get the thumb bound and get its left value
int x = seekBar.getThumb().getBounds().left;
// set the left value to textview x value
yourTextView.setX(x);
}
You can do the following:
1) MainActivity.class:
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private SeekBar sb;
private RelativeLayout rlMarker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sb = (SeekBar) findViewById(R.id.sb);
rlMarker = (RelativeLayout) findViewById(R.id.rlMarker);
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
updateMarker(sb, rlMarker, (i + " miles"));
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
rlMarker.setVisibility(View.VISIBLE);
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
rlMarker.setVisibility(View.GONE);
}
});
//initialize
updateMarker(sb, rlMarker, "0 miles");
}
private void updateMarker(final SeekBar sb,
View rlMarker,
String message) {
final TextView tvProgress = (TextView) rlMarker.findViewById(R.id.tvProgress);
final View vArrow = (View) rlMarker.findViewById(R.id.vArrow);
/**
* According to this question:
* https://stackoverflow.com/questions/20493577/android-seekbar-thumb-position-in-pixel
* one can find the SeekBar thumb location in pixels using:
*/
int width = sb.getWidth()
- sb.getPaddingLeft()
- sb.getPaddingRight();
final int thumbPos = sb.getPaddingLeft()
+ width
* sb.getProgress()
/ sb.getMax() +
//take into consideration the margin added (in this case it is 10dp)
Math.round(convertDpToPixel(10, MainActivity.this));
tvProgress.setText(message);
tvProgress.post(new Runnable() {
#Override
public void run() {
final Display display = ((WindowManager) MainActivity.this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
final Point deviceDisplay = new Point();
display.getSize(deviceDisplay);
//vArrow always follow seekBar thumb location
vArrow.setX(thumbPos - sb.getThumbOffset());
//unlike vArrow, tvProgress will not always follow seekBar thumb location
if ((thumbPos - tvProgress.getWidth() / 2 - sb.getPaddingLeft()) < 0) {
//part of the tvProgress is to the left of 0 bound
tvProgress.setX(vArrow.getX() - 20);
} else if ((thumbPos + tvProgress.getWidth() / 2 + sb.getPaddingRight()) > deviceDisplay.x) {
//part of the tvProgress is to the right of screen width bound
tvProgress.setX(vArrow.getX() - tvProgress.getWidth() + 20 + vArrow.getWidth());
} else {
//tvProgress is between 0 and screen width bounds
tvProgress.setX(thumbPos - tvProgress.getWidth() / 2f);
}
}
});
}
/**
* According to this question:
* https://stackoverflow.com/questions/4605527/converting-pixels-to-dp
* one can convert dp to pixels using the following method:
*/
public static float convertDpToPixel(float dp, Context context) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float px = dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
return px;
}
}
2) activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimaryDark"
android:textSize="40sp"
android:layout_alignParentTop="true"
android:gravity="center"
android:text="Top"
android:layout_above="#id/v"
android:textColor="#android:color/white"/>
<include
layout="#layout/marker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_above="#id/v">
</include>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_above="#id/sb"
android:id="#+id/v">
</View>
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/sb"
android:layout_centerInParent="true"
android:layout_marginRight="10dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:max="100"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:textSize="40sp"
android:gravity="center"
android:text="Bottom"
android:layout_below="#id/sb"
android:layout_alignParentBottom="true"
android:textColor="#android:color/white"/>
</RelativeLayout>
3) marker.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:id="#+id/rlMarker">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvProgress"
android:gravity="center"
android:padding="10dp"
android:textColor="#android:color/white"
android:background="#drawable/marker_shape"
android:text="0 miles"/>
<View
android:layout_width="20dp"
android:layout_height="20dp"
android:id="#+id/vArrow"
android:gravity="center"
android:rotation="180"
android:layout_below="#id/tvProgress"
android:background="#drawable/marker_arrow_shape"/>
</RelativeLayout>
4) marker_shape.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%">
<shape>
<solid
android:shape="rectangle"
android:color="#color/colorAccent" />
<corners
android:bottomLeftRadius="5dp"
android:bottomRightRadius="5dp"
android:topLeftRadius="5dp"
android:topRightRadius="5dp"/>
</shape>
</rotate>
</item>
</layer-list>
5) marker_arrow_shape.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="-40%"
android:pivotY="87%">
<shape>
<solid
android:shape="rectangle"
android:color="#color/colorAccent" />
</shape>
</rotate>
</item>
</layer-list>
6) Result:
I want to create a drawable like this for my progress bar
and I've tried this code, but I didnt get what I want
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/progress">
<shape
android:innerRadiusRatio="3"
android:shape="ring"
android:useLevel="false">
<gradient
android:centerColor="#ffff00"
android:endColor="#00ff00"
android:startColor="#fb0000"
android:type="sweep" />
</shape>
</item>
</layer-list>
This is what I've got
Is it possible to do this with only xml?
Or this is should be done with java code?
Since you asked in comments how do you do that and I can't put these links in a comment, I'll suggest you these three links. Read them and extract what you want:
how to draw a half circle in android
Draw a semicircle in the background of a View
https://github.com/devadvance/circularseekbar
Here's the solution for your question.
DifferentColorCircularBorder.java
public class DifferentColorCircularBorder {
private RelativeLayout parentLayout;
public DifferentColorCircularBorder(RelativeLayout parentLayout) {
this.parentLayout = parentLayout;
}
public void addBorderPortion(Context context, int color, int startDegree, int endDegree) {
ProgressBar portion = getBorderPortion(context, color, startDegree, endDegree);
parentLayout.addView(portion);
}
private ProgressBar getBorderPortion(Context context, int color, int startDegree, int endDegree) {
LayoutInflater inflater = LayoutInflater.from(context);
ProgressBar portion = (ProgressBar) inflater.inflate(R.layout.border_portion, parentLayout, false);
portion.setRotation(startDegree);
portion.setProgress(endDegree - startDegree);
portion.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) portion.getLayoutParams();
params.addRule(RelativeLayout.CENTER_IN_PARENT);
portion.setLayoutParams(params);
return portion;
}
}
border_portion.xml
<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="220dp"
android:layout_height="220dp"
android:progressDrawable="#drawable/circle_exterior"
android:layout_centerInParent="true"
android:max="360"/>
circle_exterior.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadius="100dp"
android:thickness="10dp" >
<solid android:color="#ff111111" />
</shape>
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout interiorLayout = (RelativeLayout) findViewById(R.id.interior);
DifferentColorCircularBorder border = new DifferentColorCircularBorder(interiorLayout);
border.addBorderPortion(getApplicationContext(), ContextCompat.getColor(com.diffcolorborder.MainActivity.this, R.color.colorGoogleBlue), 0, 50);
border.addBorderPortion(getApplicationContext(), ContextCompat.getColor(com.diffcolorborder.MainActivity.this, R.color.colorGoogleGreen), 50, 120);
border.addBorderPortion(getApplicationContext(), ContextCompat.getColor(com.diffcolorborder.MainActivity.this, R.color.colorGoogleYellow), 120, 220);
border.addBorderPortion(getApplicationContext(), ContextCompat.getColor(com.diffcolorborder.MainActivity.this, R.color.colorGoogleRed), 220, 360);
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#2d2d2d">
<RelativeLayout
android:id="#+id/interior"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:background="#drawable/profilepic" />
</RelativeLayout>
</RelativeLayout>
Any one know how to set background blurr when progressbar wheel is running in andorid. I want that screen looks like blurr when circular wheel progress bar is running and no interaction in background.
I am using this code as i required same as you, which is best fit to your requirement too.
You can write this code in your base activity class and use it as your requirement.
ViewGroup progressView;
protected boolean isProgressShowing = false;
public void showProgressingView() {
if (!isProgressShowing) {
isProgressShowing = true;
progressView = (ViewGroup) getLayoutInflater().inflate(R.layout.progressbar_layout, null);
View v = this.findViewById(android.R.id.content).getRootView();
ViewGroup viewGroup = (ViewGroup) v;
viewGroup.addView(progressView);
}
}
public void hideProgressingView() {
View v = this.findViewById(android.R.id.content).getRootView();
ViewGroup viewGroup = (ViewGroup) v;
viewGroup.removeView(progressView);
isProgressShowing = false;
}
here progressbar_layout.xml is
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#BA000000">
<ProgressBar
android:id="#+id/progressBar1"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
/>
</RelativeLayout>
This is simple and neat way to do this.
You can customize your progressbar_layout in any way, any color, any style.
Get rid of default android progress bar
Put ProgressBar control to your layout xml
<ProgressBar
android:id="#+id/progressBarDialog"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="gone"
android:indeterminateDrawable="#drawable/myDialog" >
</ProgressBar>
Assign Id into your activity
private ProgressBar bar;
bar = (ProgressBar) findViewById(R.id.progressBarDialog);
Make one xml file named myDialog.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360">
<shape
android:innerRadiusRatio="3"
android:shape="ring"
android:thicknessRatio="8"
android:useLevel="false">
<size
android:width="48dip"
android:height="48dip" />
<gradient
android:centerColor="#color/color_preloader_center"
android:centerY="0.50"
android:endColor="#color/color_preloader_end"
android:startColor="#color/color_preloader_start"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
put following code in colors.xml
<color name="color_preloader_start">#000000</color>
<color name="color_preloader_center">#000000</color>
<color name="color_preloader_end">#ff56a9c7</color>
use simple progress bar in your xml
use dependancy
compile 'jp.wasabeef:blurry:2.1.1' in build.gradle
give id (content) to your xml which you want to blur during progress bar
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="#+id/content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
in java copy this blurall() function
private void blurall() {
if (blurred) {
Blurry.delete((ViewGroup) findViewById(R.id.content));
} else {
long startMs = System.currentTimeMillis();
Blurry.with(viewprofile.this)
.radius(25)
.sampling(2)
.async()
.animate(500)
.onto((ViewGroup) findViewById(R.id.content));
Log.d(getString(R.string.app_name),
"TIME " + String.valueOf(System.currentTimeMillis() - startMs) + "ms");
}
blurred = !blurred;
}
first time call blurall() function will blur all your screen and second time call blurall() function will remove blur.Call blurall() function before progress bar start like
blurall();
progressBar.setVisibility(View.VISIBLE);
after that call again blurall() function after
progressBar.setVisibility(View.Gone);
blurall();
I am working with this, and it works perfectly for me.
In XML
<View
android:id="#+id/bgBox"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp"
android:background="#drawable/rounded_trans_overlay"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="#+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="30dp"
android:elevation="10dp"
android:foregroundGravity="center"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
rounded_trans_overlay.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#AAb9ebed"/>
<stroke
android:width="0.5dp"
android:color="#66295A75" />
<corners android:radius="20dp" />
</shape>
in Java have this function
public void loading(boolean val, Activity activity, ProgressBar progressBar, View view) {
if (val) {
view.setElevation(8);
progressBar.setVisibility(View.VISIBLE);
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
} else {
view.setElevation(0);
progressBar.setVisibility(View.GONE);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}
}
To activate Call
loading(true, requireActivity(), binding.loading, binding.bgBox);
To deactivate
loading(false, requireActivity(), binding.loading, binding.bgBox);
simply add this line in your java code
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,WindowManager.LayoutParams.FLAG_
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
How do I create a ListView with rounded corners in Android?
Here is one way of doing it (Thanks to Android Documentation though!):
Add the following into a file (say customshape.xml) and then place it in (res/drawable/customshape.xml)
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#SomeGradientBeginColor"
android:endColor="#SomeGradientEndColor"
android:angle="270"/>
<corners
android:bottomRightRadius="7dp"
android:bottomLeftRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp"/>
</shape>
Once you are done with creating this file, just set the background in one of the following ways:
Through Code:
listView.setBackgroundResource(R.drawable.customshape);
Through XML, just add the following attribute to the container (ex: LinearLayout or to any fields):
android:background="#drawable/customshape"
Hope someone finds it useful...
Although that did work, it took out the entire background colour as well. I was looking for a way to do just the border and just replace that XML layout code with this one and I was good to go!
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="4dp" android:color="#FF00FF00" />
<padding android:left="7dp" android:top="7dp"
android:right="7dp" android:bottom="7dp" />
<corners android:radius="4dp" />
</shape>
#kris-van-bael
For those having issues with selection highlight for the top and bottom row where the background rectangle shows up on selection you need to set the selector for your listview to transparent color.
listView.setSelector(R.color.transparent);
In color.xml just add the following -
<color name="transparent">#00000000</color>
Update
The solution these days is to use a CardView with support for rounded corners built in.
Original answer*
Another way I found was to mask out your layout by drawing an image over the top of the layout. It might help you. Check out Android XML rounded clipped corners
The other answers are very useful, thanks to the authors!
But I could not see how to customise the rectangle when highlighting an item upon selection rather than disabling the highlighting #alvins #bharat dojeha.
The following works for me to create a rounded list view item container with no outline and a lighter grey when selected of the same shape:
Your xml needs to contain a selector such as e.g. ( in res/drawable/customshape.xml):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true" >
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke android:width="8dp" android:color="#android:color/transparent" />
<padding android:left="14dp" android:top="14dp"
android:right="14dp" android:bottom="14dp" />
<corners android:radius="10dp" />
<gradient
android:startColor="#android:color/background_light"
android:endColor="#android:color/transparent"
android:angle="225"/>
</shape>
</item>
<item android:state_pressed="false">
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke android:width="8dp" android:color="#android:color/transparent" />
<padding android:left="14dp" android:top="14dp"
android:right="14dp" android:bottom="14dp" />
<corners android:radius="10dp" />
<gradient
android:startColor="#android:color/darker_gray"
android:endColor="#android:color/transparent"
android:angle="225"/>
</shape>
</item>
Then you need to implement a list adapter and override the getView method to set the custom selector as background
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//snip
convertView.setBackgroundResource(R.drawable.customshape);
//snip
}
and need to also 'hide' the default selector rectangle e.g in onCreate (I also hide my thin grey divider line between the items):
listView.setSelector(android.R.color.transparent);
listview.setDivider(null);
This approach solves a general solution for drawables, not just ListViewItem with various selection states.
Yet another solution to selection highlight problems with first, and last items in the list:
Add padding to the top and bottom of your list background equal to or greater than the radius. This ensures the selection highlighting doesn't overlap with your corner curves.
This is the easiest solution when you need non-transparent selection highlighting.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#color/listbg" />
<stroke
android:width="2dip"
android:color="#D5D5D5" />
<corners android:radius="10dip" />
<!-- Make sure bottom and top padding match corner radius -->
<padding
android:bottom="10dip"
android:left="2dip"
android:right="2dip"
android:top="10dip" />
</shape>
actually, i think the best solution is described on this link:
http://blog.synyx.de/2011/11/android-listview-with-rounded-corners/
in short, it uses a different background for the top, middle and bottom items, so that the top and bottom ones would be rounded.
This was incredibly handy to me. I would like to suggest another workaround to perfectly highlight the rounded corners if you are using your own CustomAdapter.
Defining XML Files
First of all, go inside your drawable folder and create 4 different shapes:
shape_top
<gradient
android:startColor="#ffffff"
android:endColor="#ffffff"
android:angle="270"/>
<corners
android:topLeftRadius="10dp"
android:topRightRadius="10dp"/>
shape_normal
<gradient
android:startColor="#ffffff"
android:endColor="#ffffff"
android:angle="270"/>
<corners
android:topLeftRadius="10dp"
android:topRightRadius="10dp"/>
shape_bottom
<gradient
android:startColor="#ffffff"
android:endColor="#ffffff"
android:angle="270"/>
<corners
android:bottomRightRadius="10dp"
android:bottomRightRadius="10dp"/>
shape_rounded
<gradient
android:startColor="#ffffff"
android:endColor="#ffffff"
android:angle="270"/>
<corners
android:topLeftRadius="10dp"
android:topRightRadius="10dp"
android:bottomRightRadius="10dp"
android:bottomRightRadius="10dp"/>
Now, create a different row layout for each shape, i.e. for shape_top :
You can also do this programatically changing the background.
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:layout_marginRight="10dp"
android:fontFamily="sans-serif-light"
android:text="TextView"
android:textSize="22dp" />
<TextView
android:id="#+id/txtValue1"
android:layout_width="match_parent"
android:layout_height="48dp"
android:textSize="22dp"
android:layout_gravity="right|center"
android:gravity="center|right"
android:layout_marginLeft="20dp"
android:layout_marginRight="35dp"
android:text="Fix"
android:scaleType="fitEnd" />
And define a selector for each shaped-list, i.e. for shape_top:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Selected Item -->
<item android:state_selected="true"
android:drawable="#drawable/shape_top" />
<item android:state_activated="true"
android:drawable="#drawable/shape_top" />
<!-- Default Item -->
<item android:state_selected="false"
android:drawable="#android:color/transparent" />
</selector>
Change your CustomAdapter
Finally, define the layout options inside your CustomAdapter:
if(position==0)
{
convertView = mInflater.inflate(R.layout.list_layout_top, null);
}
else
{
convertView = mInflater.inflate(R.layout.list_layout_normal, null);
}
if(position==getCount()-1)
{
convertView = mInflater.inflate(R.layout.list_layout_bottom, null);
}
if(getCount()==1)
{
convertView = mInflater.inflate(R.layout.list_layout_unique, null);
}
And that's done!
to make border u have to make another xml file with property of solid and corners in the drawable folder and calls it in background
I'm using a custom view that I layout on top of the other ones and that just draws the 4 small corners in the same color as the background. This works whatever the view contents are and does not allocate much memory.
public class RoundedCornersView extends View {
private float mRadius;
private int mColor = Color.WHITE;
private Paint mPaint;
private Path mPath;
public RoundedCornersView(Context context) {
super(context);
init();
}
public RoundedCornersView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.RoundedCornersView,
0, 0);
try {
setRadius(a.getDimension(R.styleable.RoundedCornersView_radius, 0));
setColor(a.getColor(R.styleable.RoundedCornersView_cornersColor, Color.WHITE));
} finally {
a.recycle();
}
}
private void init() {
setColor(mColor);
setRadius(mRadius);
}
private void setColor(int color) {
mColor = color;
mPaint = new Paint();
mPaint.setColor(mColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
invalidate();
}
private void setRadius(float radius) {
mRadius = radius;
RectF r = new RectF(0, 0, 2 * mRadius, 2 * mRadius);
mPath = new Path();
mPath.moveTo(0,0);
mPath.lineTo(0, mRadius);
mPath.arcTo(r, 180, 90);
mPath.lineTo(0,0);
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
/*Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawRect(0, 0, mRadius, mRadius, paint);*/
int w = getWidth();
int h = getHeight();
canvas.drawPath(mPath, mPaint);
canvas.save();
canvas.translate(w, 0);
canvas.rotate(90);
canvas.drawPath(mPath, mPaint);
canvas.restore();
canvas.save();
canvas.translate(w, h);
canvas.rotate(180);
canvas.drawPath(mPath, mPaint);
canvas.restore();
canvas.translate(0, h);
canvas.rotate(270);
canvas.drawPath(mPath, mPaint);
}
}
There are different ways to achieve it. The latest approach is using CardView for each ListItem component.
Here are some steps.
Create a layout resource file; let's name it "listitem.xml
Copy and paste the under enclosed Listitem.xml layout body into it.
Create RowItem class for each listitem data; later you will instantiate this to assign values for each list item. Check Code below, RowItem.class.
Create a custom ListAdapter; let's name it ListAdapter.class, and inflate this (#1) list item layout for each list item (Check the second code snippet for this one)
Set this adapter (#3) the way you set default adapters inside an activity the listview belongs to. maybe the only difference would be you first have to instantiate RowItem class with values and add RowItem object to your adapter then notify your adapter that the data is changed.
**listitem.xml**
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alignmentMode="alignMargins"
android:columnCount="1"
android:columnOrderPreserved="false"
android:rowCount="1">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_margin="6dp"
app:cardCornerRadius="8dp"
app:cardElevation="6dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="#+id/sampleiconimageID"
android:layout_width="60dp"
android:layout_height="60dp"
android:padding="5dp"/>
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/titleoflistview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Main Heading"
android:textStyle="bold" />
<TextView
android:id="#+id/samplesubtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sub Heading"
/>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</GridLayout>
</LinearLayout>
RowItem.Class
public class RowItem {
private String heading;
private String subHeading;
private int smallImageName;
private String datetime;
private int count;
public void setHeading( String theHeading ) {
this.heading = theHeading;
}
public String getHeading() {
return this.heading;
}
public void setSubHeading( String theSubHeading ) {
this.subHeading = theSubHeading;
}
public String getSubHeading( ) {
return this.subHeading;
}
public void setSmallImageName(int smallName) {
this.smallImageName = smallName;
}
public int getSmallImageName() {
return this.smallImageName;
}
public void setDate(String datetime) {
this.datetime = datetime;
}
public String getDate() {
return this.datetime;
}
public void setCount(int count) {
this.count = count;
}
public int getCount() {
return this.count;
}
}
Sample ListAdapter
public class ListAdapter extends BaseAdapter {
private ArrayList<RowItem> singleRow;
private LayoutInflater thisInflater;
public ListAdapter(Context context, ArrayList<RowItem> aRow){
this.singleRow = aRow;
thisInflater = ( LayoutInflater.from(context) );
}
#Override
public int getCount() {
return singleRow.size(); }
#Override
public Object getItem(int position) {
return singleRow.get( position ); }
#Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
view = thisInflater.inflate( R.layout.mylist2, parent, false );
//set listview objects here
//example
TextView titleText = (TextView) view.findViewById(R.id.titleoflistview);
RowItem currentRow = (RowItem) getItem(position);
titleText.setText( currentRow.getHeading() );
}
return view;
// LayoutInflater inflater=.getLayoutInflater();
// View rowView=inflater.inflate(R.layout.mylist, null,true);
//
// titleText.setText(maintitle[position]);
// subtitleText.setText(subtitle[position]);
// return null;
};
}