I am developing an android app with GridView. The gridView contains buttons. I have customized my gridView with button adapter.
The question is: I need to keep the selected item highlighted with borders. Now the selection is disappearing after releasing the press. I am not an expert in android. So the next step after pressing the button is to display an image of cloud shape that says "confirm".
This is what I exactly needed.
Create a folder named drawable in your res folder. Now create a xml file in drawable folder, name it anything (in small laters) and put this code in the file.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="true"><shape>
<!-- <solid android:color="#CCCCCC"/> -->
<gradient android:endColor="#67A7F8" android:startColor="#1067C8" />
<stroke android:width="1dp" android:color="#000000" />
<corners android:radius="8dp" />
</shape></item>
<item android:state_focused="false" android:state_pressed="true"><shape>
<!-- <solid android:color="#07B107"/> -->
<gradient android:endColor="#67A7F8" android:startColor="#1067C8" />
<stroke android:width="1dp" android:color="#000000" />
<corners android:radius="8dp" />
</shape></item>
<item android:state_focused="true" android:state_pressed="false"><shape>
<solid android:color="#FFFFFF" />
<stroke android:width="1dp" android:color="#0055FF" />
<corners android:radius="8dp" />
</shape></item>
<item android:state_focused="false" android:state_pressed="false"><shape>
<gradient android:angle="270" android:centerColor="#FFFFFF" android:endColor="#FFFFFF" android:startColor="#F2F2F2" />
<stroke android:width="0.8dp" android:color="#000000" />
<corners android:radius="12dp" />
</shape></item>
<item android:state_enabled="true"><shape>
<padding android:bottom="4dp" android:left="5dp" android:right="4dp" android:top="4dp" />
</shape></item>
</selector>
now in your GridView code set android:drawSelectorOnTop="true" and android:listSelector properties and select the drawable you have just created. It will resolve your problem.
Your grid view code will look something like this :
<GridView
android:id="#+id/lstFrames_available_frames"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:animateLayoutChanges="true"
android:columnWidth="100dp"
android:gravity="center"
android:horizontalSpacing="3dp"
android:listSelector="#drawable/round_buttons"
android:numColumns="auto_fit"
android:drawSelectorOnTop="true"
android:stretchMode="columnWidth"
android:verticalSpacing="3dp" >
</GridView>
UPDATE
You can use something like this in your custom adapter to achieve what you want :
public class AlbumCoverAdapter extends BaseAdapter {
private Activity activity;
private static LayoutInflater inflater = null;
private int mSelected;
public AlbumCoverAdapter(Activity a) {
activity = a;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return 50;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public static class ViewHolder {
public TextView txtCaption;
public ImageView imgImage;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
ViewHolder holder;
if (convertView == null) {
vi = inflater.inflate(R.layout.grid_adapter, null);
holder = new ViewHolder();
holder.txtCaption = (TextView)vi.findViewById(R.id.txtGridText);
holder.txtCaption.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
mSelected = (Integer)arg0.getTag();
notifyDataSetChanged();
}
});
vi.setTag(holder);
} else
holder = (ViewHolder)vi.getTag();
try {
holder.txtCaption.setTag(position);
if (position == mSelected) {
holder.txtCaption.setBackgroundResource(R.drawable.round_corner_background);
} else {
holder.txtCaption.setBackgroundDrawable(null);
}
holder.txtCaption.setText("Item: " + position);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return vi;
}
}
Related
I want to add text inside switches and expect toggle to completely cover the texts
I was able to achieve this in API 16 with below option
<Switch
android:textOff="off"
android:showText="true"
android:textOn="on"/>
However same switch looks odd in the higher version(i'm testing with API 27) where switch toggle is a round icon behind the text.
Is there a way i can fit the text inside the switch toggle using native library/methods.
I found this code in GitHub. After some addition and modification, I get what I need. This toggle button has YES NO text on it and works like switch button. You can give it a go.
public class ToggleButton extends RelativeLayout implements View.OnClickListener {
FrameLayout layout;
TextView toggleCircle;
View background_oval_off, background_oval_on;
int dimen;
private Boolean _crossfadeRunning = false;
private ObjectAnimator _oaLeft, _oaRight;
public ToggleButton(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.toggle_button, this, true);
background_oval_off = findViewById(R.id.background_oval_off);
background_oval_on = findViewById(R.id.background_oval_on);
toggleCircle = findViewById(R.id.toggleCircle);
layout = (FrameLayout) findViewById(R.id.layout);
layout.setOnClickListener(this);
//get a pixel size for a particular dimension - will differ by device according to screen density
dimen = getResources().getDimensionPixelSize(R.dimen.toggle_width);
_oaLeft = ObjectAnimator.ofFloat(toggleCircle, "x", dimen / 2, 0).setDuration(250);
_oaRight = ObjectAnimator.ofFloat(toggleCircle, "x", 0, dimen / 2).setDuration(250);
//setState();
}
public ToggleButton(Context context) {
this(context, null);
}
public void setState(String answer) {
Log.d("simul", "ans - " + answer);
if (answer.equals("1")) {
toggleCircle.setTextColor(ContextCompat.getColor(getContext(), R.color.green));
toggleCircle.setX(dimen / 2);
_crossfadeViews(background_oval_off, background_oval_on, 1);
toggleCircle.setText("Yes");
} else {
toggleCircle.setTextColor(ContextCompat.getColor(getContext(), R.color.red));
toggleCircle.setX(0);
_crossfadeViews(background_oval_on, background_oval_off, 1);
toggleCircle.setText("No");
}
}
private void _crossfadeViews(final View begin, View end, int duration) {
_crossfadeRunning = true;
end.setAlpha(0f);
end.setVisibility(View.VISIBLE);
end.animate().alpha(1f).setDuration(duration).setListener(null);
begin.animate().alpha(0f).setDuration(duration).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
begin.setVisibility(View.GONE);
_crossfadeRunning = false;
}
});
}
#Override
public void onClick(View view) {
if (_oaLeft.isRunning() || _oaRight.isRunning() || _crossfadeRunning) return;
if (toggleCircle.getText().equals("Yes")) {
_oaLeft.start();
_crossfadeViews(background_oval_on, background_oval_off, 110);
toggleCircle.setText("No");
toggleCircle.setTextColor(ContextCompat.getColor(getContext(), R.color.red));
mListener.toggleButtonClickListener("No");
} else {
_oaRight.start();
_crossfadeViews(background_oval_off, background_oval_on, 400);
toggleCircle.setText("Yes");
toggleCircle.setTextColor(ContextCompat.getColor(getContext(), R.color.green));
mListener.toggleButtonClickListener("Yes");
}
}
public ToggleButtonListener mListener = null;
public void setToggleButtonClickListener(ToggleButtonListener listener) {
mListener = listener;
}
public interface ToggleButtonListener {
public void toggleButtonClickListener(String content);
}
}
toogle_button_red_oval.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:right="#dimen/toggle_circle_diameter">
<shape android:shape="oval">
<solid android:color="#color/red"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
</item>
<item android:left="#dimen/toggle_circle_radius" android:right="#dimen/toggle_circle_radius">
<shape android:shape="rectangle">
<solid android:color="#color/red"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
</item>
<item android:left="#dimen/toggle_circle_diameter">
<shape android:shape="oval">
<solid android:color="#color/red"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
</item>
</layer-list>
toogle_button_green_oval.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:right="#dimen/toggle_circle_diameter">
<shape android:shape="oval">
<solid android:color="#color/green"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
</item>
<item android:left="#dimen/toggle_circle_radius" android:right="#dimen/toggle_circle_radius">
<shape android:shape="rectangle">
<solid android:color="#color/green"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
</item>
<item android:left="#dimen/toggle_circle_diameter">
<shape android:shape="oval">
<solid android:color="#color/green"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
</item>
</layer-list>
toogle_button_circle.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#color/white"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
toogle_button.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
android:id="#+id/layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<View
android:layout_width="#dimen/toggle_width"
android:layout_height="#dimen/toggle_height"
android:id="#+id/background_oval_off"
android:background="#drawable/toggle_button_black_oval" />
<View
android:layout_width="#dimen/toggle_width"
android:layout_height="#dimen/toggle_height"
android:id="#+id/background_oval_on"
android:background="#drawable/toggle_button_green_oval"
android:visibility="gone" />
<TextView
android:paddingTop="10dp"
android:paddingLeft="10dp"
android:layout_width="#dimen/toggle_circle_diameter"
android:layout_height="#dimen/toggle_circle_diameter"
android:layout_gravity="center_vertical"
android:id="#+id/toggleCircle"
android:textSize="#dimen/toggle_text_size"
android:text="No"
android:background="#drawable/toggle_button_circle"/>
</FrameLayout>
</merge>
XML layout code
<package.name.ToggleButton
android:id="#+id/toggleButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</cpackage.name.ToggleButton>
Java Code :
ToggleButton toggleButton = findViewById(R.id.toggleButton);
toggleButton.setToggleButtonClickListener(new ToggleButton.ToggleButtonListener() {
#Override
public void toggleButtonClickListener(String content) {
if (content.equals("Yes")) {
} else {
}
}
});
dimens.xml
<dimen name="toggle_width">100dp</dimen>
<dimen name="toggle_height">50dp</dimen>
<dimen name="toggle_circle_diameter">50dp</dimen>
<dimen name="toggle_circle_radius">25dp</dimen>
Sorry for this long long answer. I had to add all the code here. please let me know if anything missing here. :)
I am not able to show the shadow of the indicator above the indicatior height within the tabs. i am using the karim library for material tabs,where i apply elevation but that does not help.How can i accheive shadow within the tab?
layout
<io.karim.MaterialTabs
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_alignParentBottom="true"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:background="#android:color/transparent"
android:textColor="#color/white"
app:mtIndicatorColor="#color/colorPrimaryRed"
app:mtIndicatorHeight="3dp"
app:mtPaddingMiddle="false"
app:mtSameWeightTabs="true"
app:mtTabPaddingLeftRight="10dp" />
test drawable
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<layer-list>
<item android:left="-11dp" android:right="-11dp" android:top="-11dp">
<shape>
<stroke android:width="10dp" android:color="#color/colorPrimaryRed" />
<gradient android:angle="90" android:endColor="#00fafafa" android:startColor="#88d66f67" android:type="linear" />
<corners android:radius="2dp" />
<padding android:bottom="3dp" android:left="3dp" android:right="3dp" android:top="3dp" />
</shape>
</item>
</layer-list>
</item>
</selector>
java
class StarterMenuAdapter extends FragmentPagerAdapter {
public StarterMenuAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == 1) {
LoginFragment loginFragment = new LoginFragment();
return loginFragment;
} else {
RegisterFragment registerFragment = new RegisterFragment();
return registerFragment;
}
}
#Override
public CharSequence getPageTitle(int position) {
return CONTENT[position % CONTENT.length].toUpperCase();
}
#Override
public int getCount() {
return CONTENT.length;
}
}
want to achieve
what i got
how can shadow within the tab be achieved?
It is similar as you want,
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<layer-list>
<item android:left="-8dp" android:right="-8dp" android:top="-8dp">
<shape>
<stroke android:width="7dp" android:color="#color/red" />
<gradient android:angle="90" android:endColor="#00fafafa" android:startColor="#88d66f67" android:type="linear" />
<corners android:radius="2dp" />
<padding android:bottom="3dp" android:left="3dp" android:right="3dp" android:top="3dp" />
</shape>
</item>
</layer-list>
</item>
</selector>
Output
I'm using RecyclerView to display a few resource-consuming images. My implementation looks like the following:
private class NoteConfigItemAdapter extends RecyclerView.Adapter<NoteConfigItemAdapter.NoteConfigViewHolder> {
public class NoteConfigViewHolder extends RecyclerView.ViewHolder {
private final ToggleButton tbButton;
private final TextView tvDescription;
private int index;
private final View.OnClickListener buttonClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
int oldSelectedItem = selectedItem;
selectedItem = index;
notifyItemChanged(oldSelectedItem);
notifyItemChanged(selectedItem);
}
};
public NoteConfigViewHolder(View itemView) {
super(itemView);
tbButton = (ToggleButton)itemView.findViewById(R.id.notesConfig_tbButton);
tvDescription = (TextView)itemView.findViewById(R.id.notesConfig_tvDescription);
tbButton.setOnClickListener(this.buttonClickListener);
}
public void setData(int descriptionResource, int drawableResource, int index) {
this.index = index;
tvDescription.setText(descriptionResource);
Drawable background = ResourcesCompat.getDrawable(getResources(), drawableResource, null);
tbButton.setBackground(background);
tbButton.setChecked(index == selectedItem);
}
}
private List<NoteConfigItem> configItems;
private int layoutResource;
private int selectedItem = 0;
public NoteConfigItemAdapter(List<NoteConfigItem> configItems, int layoutResource) {
this.configItems = configItems;
this.layoutResource = layoutResource;
}
#Override
public NoteConfigViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater
.from(parent.getContext())
.inflate(layoutResource, parent, false);
return new NoteConfigViewHolder(itemView);
}
#Override
public void onBindViewHolder(NoteConfigViewHolder holder, int position) {
NoteConfigItem item = configItems.get(position);
holder.setData(item.stringResource, item.drawableResource, position);
}
#Override
public int getItemCount() {
return configItems.size();
}
}
Single item's layout contains only ToggleButton and TextView:
I'm dynamically assigning background to the ToggleButton upon binding. Background is a Drawable, which defines two states for the button:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<layer-list>
<item>
<shape android:shape="rectangle">
<solid android:color="#color/colorPrimary" />
</shape>
</item>
<item>
<inset android:insetTop="#dimen/selectionBorderSize"
android:insetLeft="#dimen/selectionBorderSize"
android:insetRight="#dimen/selectionBorderSize"
android:insetBottom="#dimen/selectionBorderSize">
<layer-list>
<item>
<shape android:shape="rectangle">
<solid android:color="#ffffff"></solid>
</shape>
</item>
<item>
<bitmap android:src="#drawable/full_range" >
<padding android:bottom="#dimen/selectionBorderSize"
android:top="#dimen/selectionBorderSize"
android:left="#dimen/selectionBorderSize"
android:right="#dimen/selectionBorderSize" />
</bitmap>
</item>
</layer-list>
</inset>
</item>
</layer-list>
</item>
<item android:state_checked="false">
<layer-list>
<item>
<shape android:shape="rectangle">
<solid android:color="#ffffff" />
</shape>
</item>
<item>
<inset android:insetTop="#dimen/selectionBorderSize"
android:insetLeft="#dimen/selectionBorderSize"
android:insetRight="#dimen/selectionBorderSize"
android:insetBottom="#dimen/selectionBorderSize">
<layer-list>
<item>
<shape android:shape="rectangle">
<solid android:color="#ffffff"></solid>
</shape>
</item>
<item>
<bitmap android:src="#drawable/full_range" >
<padding android:bottom="#dimen/selectionBorderSize"
android:top="#dimen/selectionBorderSize"
android:left="#dimen/selectionBorderSize"
android:right="#dimen/selectionBorderSize" />
</bitmap>
</item>
</layer-list>
</inset>
</item>
</layer-list>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#ffffff" />
</shape>
</item>
</selector>
#drawable/fullRange is a PNG image. Itself it is not so big (~hundred of such images occupy around 400kb), but it is quite big (225px x 450px), so I guess the bitmap object created from this PNG can be memory-costly.
When I run the application, I monitor the memory usage. When I only scroll through RecyclerViews, the chart looks like the following:
But when I start to select items, occupied memory starts to grow until OutOfMemoryException:
What am I doing wrong? Why arent the resources being reused/disposed?
I have an ExpandableListView.
When a child is expanded it should be considered "selected". When a child is selected both the child and the child's children should display a different background (to show the user which is the current selected item).
Right now this is what I have:
XML
<ExpandableListView
android:id="#+id/listViewAccepted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice"
android:listSelector="#drawable/custom_selector" >
</ExpandableListView>
The ListView
setOnGroupClickListener(new OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View view,int groupPosition, long id) {
view.setSelected(true);
parent.setItemChecked(groupPosition, true);
return false;
}
});
The Selector
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<solid android:color="#color/holo_blue_light" />
</shape>
</item>
<item android:state_selected="true">
<shape>
<solid android:color="#color/green" />
</shape>
</item>
<item android:state_checked="true">
<shape>
<solid android:color="#color/green" />
</shape>
</item>
<item android:state_focused="true">
<shape>
<solid android:color="#color/green" />
</shape>
</item>
<item android:state_activated="true">
<shape>
<solid android:color="#color/green" />
</shape>
</item>
<item>
<shape>
<solid android:color="#color/transparent" />
</shape>
</item>
</selector>
Here's how i did it, the following changes the group view. The overridden method is contained in my custom ExpandableListAdapter.
#Override
public View getGroupView(int groupPosition, boolean isExpanded,
View view, ViewGroup parent)
{
LinearLayout bevGroup = (LinearLayout) view.findViewById(R.id.myid);
if(isExpanded)
{
bevGroup.setBackgroundColor(context.getResources().getColor(R.color.bgGroupBlack));
}
else
{
bevGroup.setBackgroundColor(context.getResources().getColor(R.color.bgTransparent));
}
}
And the child, only ever being visible when expanded, is always the color it's supposed to be.
I use below code to modify style of ListView item click.
list_four_corner_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="#drawable/list_four_corner_selected"
/>
<item
android:drawable="#drawable/list_four_corner_unselect"
/>
</selector>
list_four_corner_unselect.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#FFFFFF"
android:endColor="#FFFFFF"
android:angle="270"/>
<corners android:bottomLeftRadius="10dip"
android:bottomRightRadius="10dip"
android:topRightRadius="10dip"
android:topLeftRadius="10dip" />
<stroke
android:width="1dp"
android:color="#dddddd"
android:dashWidth="10dp"
android:dashGap="0dp" />
</shape>
list_four_corner_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#B7D5F9"
android:endColor="#B7D5F9"
android:angle="270"/>
<corners android:bottomLeftRadius="10dip"
android:bottomRightRadius="10dip"
android:topLeftRadius="10dip"
android:topRightRadius="10dip" />
</shape>
And below code in BaseAdapter:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewTag viewTag;
if(convertView == null) {
convertView = myInflater.inflate(R.layout.row_item, null);
viewTag = new ViewTag((TextView)convertView.findViewById(R.id.row_title));
convertView.setTag(viewTag);
}
else {
viewTag = (ViewTag)convertView.getTag();
}
convertView.setBackgroundResource(R.drawable.list_four_corner_selector);
}
But while I click item, the item's four corner will display the default color.
I want to let the default hide.
How can I do it?
Try using android:listSelector on the ListView.