Long press definition at XML layout, like android:onClick does - android

There is any way to define into XML layout longKeyLongPress definition like onClick does ?.
i.e this is my view
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:text="Line 1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/message"
android:textSize="15dip"
android:textStyle="bold"
android:textColor="#color/colorblue"
android:shadowDy="1.0"
android:shadowDx="1.0"
android:shadowRadius="1.0"
android:shadowColor="#ffffffff"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:paddingTop="5dip"
android:lineSpacingExtra="3dip"
android:lineSpacingMultiplier="1.1"
android:singleLine="false"
android:autoLink="web|email|phone|map|all"
android:onClick="clickHandler"
android:clickable="true"
/>
I want something like before but reacting to longpress event.
Note:
I don't want to add listener from my code.
I tried with android:longClickable.

The attribute is not defined, however you can implement it.
Extend TextView and let's call it MyTextView.
Then add file attrs.xml in res/values/ with following content:
<xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyTextView">
<attr name="onKeyLongPress" format="string"/>
</declare-styleable>
</resources>
In MyTextView constructor add logic to read data from xml:
public MyTextView(final Context context, final AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);
for (int i = 0; i < a.getIndexCount(); ++i)
{
int attr = a.getIndex(i);
switch (attr)
{
case R.styleable.MyTextView_onKeyLongPress: {
if (context.isRestricted()) {
throw new IllegalStateException("The "+getClass().getCanonicalName()+":onKeyLongPress attribute cannot "
+ "be used within a restricted context");
}
final String handlerName = a.getString(attr);
if (handlerName != null) {
setOnLongClickListener(new OnLongClickListener() {
private Method mHandler;
#Override
public boolean onLongClick(final View p_v) {
boolean result = false;
if (mHandler == null) {
try {
mHandler = getContext().getClass().getMethod(handlerName, View.class);
} catch (NoSuchMethodException e) {
int id = getId();
String idText = id == NO_ID ? "" : " with id '"
+ getContext().getResources().getResourceEntryName(
id) + "'";
throw new IllegalStateException("Could not find a method " +
handlerName + "(View) in the activity "
+ getContext().getClass() + " for onKeyLongPress handler"
+ " on view " + MyTextView.this.getClass() + idText, e);
}
}
try {
mHandler.invoke(getContext(), MyTextView.this);
result = true;
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not execute non "
+ "public method of the activity", e);
} catch (InvocationTargetException e) {
throw new IllegalStateException("Could not execute "
+ "method of the activity", e);
}
return result;
}
});
}
break;
}
default:
break;
}
}
a.recycle();
}
Use new attribute in your layout xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<your.package.MyTextView
android:id="#+id/theId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:onKeyLongPress="myDoSomething"
/>
<!-- Other stuff -->
</LinearLayout>
Credits:
I have learned how to do this from this post: http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/
Snippet for constructor with slight modifications was taken from original android View class.

Looking at the current documentation, such an XML parameter does not currently exist. The longClickable is a boolean parameter to define simply whether a View is responds to long clicks or not.

(10 years later, might be useful to others)
When using Databinding and MVVM you can write a Bindingadapter that works as intended:
#BindingAdapter("android:onLongClick")
fun setOnLongClickListener(view: View,block : () -> Unit) {
view.setOnLongClickListener {
block()
return#setOnLongClickListener true
}
}
You can then use it like: android:onLongClick="#{() -> vm.yourFunction()}"
You can also return the function and change Unit to boolean if you indend to return false in some cases

Related

how to add value to each item of string array in string.xml in spinner

i have a problem here in using spinner, i want to add value to each array item in my string.xml
this is my code:
<string-array name="hubungan">
<item>Choice</item>
<item>CHILD</item>
<item>PARENT</item>
<item>HUSBAND</item>
<item>WIFE</item>
</string-array>
I mean is:
<string-array name="hubungan">
<item>Choice value="1"</item>
<item>CHILD value="2"</item>
<item>PARENT value="3"</item>
<item>HUSBAND value="4"</item>
<item>WIFE value="5"</item>
</string-array>
try this
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/spinner"
android:entries="#array/hubungan"
/>
Well if you insist doing in this way try this example. The example will be as minimal as possible since you don't provide enough code.
Your string array values as you defined but I modified the way of storing by convenince.
<string-array name="hubungan">
<item>Choice,1</item>
<item>CHILD,2</item>
<item>PARENT,3</item>
<item>HUSBAND,4</item>
<item>WIFE,5</item>
</string-array>
I will assume that you have a spinner and a textview in your activity / fragment. You can set this data and process it as needed like following:
Spinner definition in xml
<Spinner
android:id="#+id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
This code must be located in your onCreate method if you use an activity, or onViewCreated method if you use a fragment.
// I assume that you've already instantiated the spinner and textview
// Setup for spinner
String[] hubungans = getResources().getStringArray(R.array.hubungan);
if(hubungans != null && hubungans.length > 0) {
String[] names = new String[hubungans.length];
String[] values = new String[hubungans.length];
// Now we will parse the records and split them into name and value
for(int i = 0; i < hubungans.length; i++) {
String hubungan = hubungans[i];
if(hubungan == null || hubungan.isEmpty()) {
Log.d(TAG, "onViewCreated: couldn't get record for index "+i);
continue;
}
// Split the record by "," seperator for example for choice "Choice,1"
String[] nameValue = hubungan.split(",");
if(nameValue.length < 2) {
Log.d(TAG, "onViewCreated: couldn't get split record for index "+i);
continue;
}
names[i] = nameValue[0]; // first index will have the names
values[i] = nameValue[1]; // second will have its value
}
Log.d(TAG, "onViewCreated: names and values: "+ Arrays.toString(names)+" - "+Arrays.toString(values));
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, names);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
int val = 0;
try {
val = Integer.parseInt(values[position]); // Here you have value as numeric type
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
textView.setText(String.format("Value for %s is %d", names[position], val));
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
} else {
Log.d(TAG, "onViewCreated: Hubungans cannot be read!");
}
There you go! Hope this helps you with your unique problem.

android multiple themes, one app

I need to develop an app, which can for some users (defined by server) set different app colors.
I have read a lot of custom theme with usage of attr.xml file, but android studio builder will be broken if I would use it.
So i have developed another approach - I subclassed Resorses class of my BaseActivity:
CustomResource customResource;
#Override
public Resources getResources() {
if (customResource == null) {
customResource = new CustomResource(super.getAssets(), super.getResources().getDisplayMetrics(), super
.getResources().getConfiguration());
}
return customResource;
}
public class CustomResource extends Resources {
public CustomResource(AssetManager assets, DisplayMetrics metrics, Configuration config) {
super(assets, metrics, config);
}
#Override
public int getColor(int id) throws NotFoundException {
Log.d("TAG", "id: " + id + " getResourceName: " + getResourceName(id));
Log.i("TAG", "Came Color: "+super.getColor(id));
return getColor ( getResourceName(id) , id);
}
public int getColor(String aString, int oldId) {
String packageName = getPackageName();
int resId = getIdentifier(getThemeColorName(aString),null,null);
Log.v("TAG", "resId: "+resId);
if (resId != 0) {
Log.i("TAG", "We SET Color: "+super.getColor(resId));
return super.getColor(resId);
} else {
return super.getColor(oldId);
}
}
private String getThemeColorName(String aString){
int pos = aString.lastIndexOf('/');
if (pos != -1){
aString = aString.substring(0, pos+1) + "b" + aString.substring(pos+1, aString.length());
}
Log.d("TAG", "aString NOW: " + aString);
return aString;
}
}
And retreive appropriet resource (just for testing, I am pulling out instead of "someColor" -> "bsomeColor".
As I look into log, everything is working, colors are being changing.
But if I set colors from xml (activities layout) I see all methods are being exected (sucessfully), but on my screen android epplyies colors without "b" prefix (BUT all my methods are being called - getColor() for every view, and I return super.getColor for an appropriate color, what I need!
Please, give me ideas how this can be solved, or give me other options to nicely introduce multiple themes, not breaking the xml editor

ListView not refreshing after updating object in the list

I've an ArrayList containing Cards. I'm trying to edit a Cards tag in the ArrayList and after editingit I want the ListView to refresh, so the user can see the updated Card, with the new tag.
I'm using cardslib for my Cards. And I'm using Android TagView Lib to tag my cards.
Here's the XML for the Card
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/colorBorder"
android:layout_width="10dp"
android:layout_height="#dimen/card_base_empty_height"
android:layout_marginTop="2dp"
android:background="#drawable/rectangle" />
<TextView
(...) />
<TextView
(...) />
<TextView
(...) />
<TextView
(...) />
<pl.charmas.android.tagview.TagView
android:id="#+id/tags_view"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_below="#id/card_main_inner_simple_total_contacts"
android:layout_marginLeft="10dp"
android:layout_alignParentRight="true"
android:textSize="12sp"/>
</RelativeLayout>
And here's when I try to edit and update the list view:
private final OnClickCardHeaderPopupMenuListener popupMenuListener = new OnClickCardHeaderPopupMenuListener() {
#Override
public void onMenuItemClick(BaseCard baseCard, MenuItem menuItem) {
final String backupId = baseCard.getId();
switch (menuItem.getItemId()) {
case R.id.action_restore:
BackupsIntentService.restoreCloudBackup(getActivity(), backupId);
Log.d(TAG, "Going to update the card");
setCurrentTask(backupId, "Restoring...", "");
break;
case R.id.action_download:
BackupsIntentService.downloadCloudBackup(getActivity(), backupId);
break;
case R.id.action_delete:
BackupsIntentService.removeCloudBackup(getActivity(), backupId);
break;
}
}
};
And here's the setCurrentTask method, where I update and refresh the list:
private void setCurrentTask(final String backupId, final String currentTaskDescription, final String separator)
{
int pos = -1;
for(int i = 0; i<cloudBackupCardList.size(); i++)
{
BackupCard backupCard = (BackupCard) cloudBackupCardList.get(i);
if(backupCard.getId().equals(backupId))
{
pos = i;
Log.d(TAG, "Found the card at position: " + i + " updating it now");
TagView.Tag[] tags = {new TagView.Tag(currentTaskDescription, Color.BLUE)};
backupCard.setCurrentTaskDescription(tags, separator);
}
}
if(pos == -1)
return;
BackupCard backupCard = (BackupCard) cloudBackupCardList.get(pos);
Log.d(TAG, "There should be: " + currentTaskDescription + " but found: " + backupCard.getCurrentTaskDescription() + " Thread: " + Thread.currentThread()
.getName());
cardListView.setAdapter(new RemoteCardArrayMultiChoiceAdapter(getActivity(), cloudBackupCardList));
// remoteCardArrayMultiChoiceAdapter.remove(remoteCardArrayMultiChoiceAdapter.getItem(pos));
// remoteCardArrayMultiChoiceAdapter.insert(backupCard, pos);
//
//// remoteCardArrayMultiChoiceAdapter.clear();
//// remoteCardArrayMultiChoiceAdapter.addAll(cloudBackupCardList);
// remoteCardArrayMultiChoiceAdapter.notifyDataSetChanged();
// cardListView.refreshDrawableState();
}
I've tried all those (the commented ones) different methods and the list is still not updated.
Here's my logcat output:
07-07 15:12:59.644: D/CardCloudBackupsFragment(24311): Going to update the card
07-07 15:12:59.644: D/CardCloudBackupsFragment(24311): Found the card at position: 8 updating it now
07-07 15:12:59.656: D/CardCloudBackupsFragment(24311): There should be: Restoring... but found: RESTORING... ThreaD: main
As you can see from the logcat, the object is updated but in the listview, on my terminal, it is not. Which leads me to conclude that the listview is not updated/refreshed. (Dont mind the all upper case letters in Restoring, it's expected.)
////////////////////// EDIT ////////////////////////////////
Here is my setupInnerViewElements method as requested in the comments box.
#Override
public void setupInnerViewElements(ViewGroup parent, View view) {
//Retrieve elements
titleTextView = (TextView) parent.findViewById(R.id.card_main_inner_simple_title);
subTitleTextView = (TextView) parent.findViewById(R.id.card_main_inner_simple_sub_title);
TextView descriptionTextView = (TextView) parent.findViewById(R.id.card_main_inner_simple_description);
TextView totalContactsTextView = (TextView) parent.findViewById(R.id.card_main_inner_simple_total_contacts);
tagView = (TagView) parent.findViewById(R.id.tags_view);
if(isLocal)
{
if (titleTextView != null)
titleTextView.setText(TIMESTAMP_TXT + titleCard); // 1st
if (subTitleTextView != null)
subTitleTextView.setText(CONTACTS_COUNT_TXT + subTitleCard); // 2nd
if(descriptionTextView != null)
descriptionTextView.setText(RESTORE_COUNT_TXT + description); // 3rd
if(tagView != null)
{
TagView.Tag[] tags = {new TagView.Tag("Wow", Color.TRANSPARENT)};
tagView.setTags( tags, "" );
}
return;
}
if (titleTextView != null)
titleTextView.setText(TIMESTAMP_TXT + titleCard); // 1st
if (subTitleTextView != null)
subTitleTextView.setText(PHONE_BRAND_TXT + subTitleCard); // 2nd
if(descriptionTextView != null)
descriptionTextView.setText(PHONE_MODEL_TXT + description); // 3rd
if(totalContactsTextView != null)
totalContactsTextView.setText(CONTACTS_COUNT_TXT + contactsNumber); // 4th
if(tagView != null)
{
TagView.Tag[] tags = {new TagView.Tag("Wow", Color.TRANSPARENT)};
tagView.setTags( tags, "" );
}
}
Replace below Line:
cardListView.setAdapter(new RemoteCardArrayMultiChoiceAdapter(getActivity(), cloudBackupCardList));
with
RemoteCardArrayMultiChoiceAdapter adapter=new RemoteCardArrayMultiChoiceAdapter(getActivity(), cloudBackupCardList));
cardListView.setAdapter(adapter);
adapter.notifyDataSetChanged();
Thats it...
The problem was a no problem at all, it was as simply as setting the tag and the TagsLibrary would take care of updating the CardView. I just didn't know this so I was trying to refresh the listview.
So I simply have this method on my card class:
public void setCurrentTaskDescription(TagView.Tag[] tags, String separator)
{
tagView.setTags(tags, separator);
}
and then on my listener I just do this:
switch ( menuItem.getItemId()) {
case R.id.action_restore:
BackupsIntentService.restoreCloudBackup(getActivity(), backupId);
EventBus.getDefault().post(new
setCurrentTask(backupCard, "Restoring...", "");
break;
}
private void setCurrentTask(final BackupCard backupCard, final String currentTaskDescription, final String separator)
{
TagView.Tag[] tags = {new TagView.Tag(currentTaskDescription, Color.GREEN)};
backupCard.setCurrentTaskDescription(tags, separator);
}
No need to refresh the list!
I was trying to make a thunderstorm inside a glass of water. Lesson learned.

Always my last row of database is not showing in alertdialog

I am developing a android App where i have to show my data on customize alert dialog from data base. This is my database
I am trying to show all these data on alert-dialog a by follwing code
public View getView(int position, View convertView, ViewGroup parent) {
Log.d(TAG, "Position " + position);
int _id = 0;
int type = getItemViewType(position);
OrderViewHolder orderViewHolder = null;
if (convertView == null) {
orderViewHolder = new OrderViewHolder();
switch (type) {
case TYPE_STATUS:
convertView = inflater.inflate(R.layout.category_header, null);
orderViewHolder.setTvTitle((TextView) convertView
.findViewById(R.id.category));
break;
case TYPE_ITEM:
convertView = inflater.inflate(R.layout.order_list_row, null);
orderViewHolder.setTvTitle((TextView) convertView
.findViewById(R.id.orderTitle));
orderViewHolder.setTvPrice((TextView) convertView
.findViewById(R.id.orderPrice));
orderViewHolder.setIvDelete((ImageButton) convertView
.findViewById(R.id.deleteOrder));
// orderViewHolder.setIvDelete((ImageButton)convertView.findViewById(R.id.deleteOrder).setLayoutParams(params))
break;
}
convertView.setTag(orderViewHolder);
} else {
orderViewHolder = (OrderViewHolder) convertView.getTag();
}
if (position == 0) {
if (starterCount != 0) {
orderViewHolder.getTvTitle().setText("");
// orderViewHolder.getTvTitle().setBackgroundDrawable(R.drawable.tab_starters_menu_on);
orderViewHolder.getTvTitle().setTextColor(R.color.Black);
orderViewHolder.getTvTitle().setTextSize(12);
orderViewHolder.getTvTitle().setTypeface(Typeface.DEFAULT_BOLD);
orderViewHolder.getTvTitle().setBackgroundResource(R.drawable.tt111);
orderViewHolder.getTvTitle().setHeight(20);
orderViewHolder.getTvTitle().setWidth(100);
/*
* RestaurantHome.setFontTextViewTahoma(OrderListAdapter,
* orderViewHolder.getTvTitle());
*/
}
else {
orderViewHolder.getTvTitle().setText(" ");
orderViewHolder.getTvTitle().setBackgroundColor(Color.WHITE);
}
}
if ((position !=0))
{
System.out.println(" position vlue : "+position);
if (oStarterCursor.moveToPosition(position-1)) {
String title = oStarterCursor.getString(oStarterCursor.getColumnIndex("item_name"));
System.out.println( " value of title "+title);
String price = oStarterCursor.getString(oStarterCursor.getColumnIndex("Item_cost"));
System.out.println( " value of price "+price);
_id = oStarterCursor.getInt(oStarterCursor
.getColumnIndex("_id"));
if (title != null) {
title = title.trim();
orderViewHolder.getTvTitle().setText(title);
orderViewHolder.getTvTitle().setTextColor(R.color.black);
orderViewHolder.getTvTitle().setTextSize(12);
orderViewHolder.getTvTitle().setTypeface(Typeface.DEFAULT);
orderViewHolder.getTvTitle().setGravity(Gravity.CENTER_VERTICAL);
}
if (price != null) {
price = price.trim();
orderViewHolder.getTvPrice().setText(price + ".00");
orderViewHolder.getTvTitle().setTextColor(R.color.black);
orderViewHolder.getTvTitle().setTextSize(12);
orderViewHolder.getTvTitle().setTypeface(Typeface.DEFAULT);
orderViewHolder.getTvTitle().setGravity(Gravity.CENTER_VERTICAL);
}
_id = oStarterCursor.getInt(oStarterCursor.getColumnIndex("_id"));
}
convertView.setTag(R.id.orderTitle, _id);
if (orderViewHolder.getIvDelete() != null) {
orderViewHolder.getIvDelete().setTag(R.id.orderTitle, _id);
}
// _id =
// oStarterCursor.getInt(oStarterCursor.getColumnIndex("_id"));
}
//}
return convertView;}
I am going to post my order_list_row.xml file.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100sp"
android:layout_height="fill_parent"
android:background="#fff" >
<ImageButton
android:id="#+id/deleteOrder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="20dp"
android:background="#fff"
android:onClick="clickHandler"
android:src="#drawable/icon_close" >
</ImageButton>
<TextView
android:id="#+id/orderTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_margin="4sp"
android:background="#fff"
android:textColor="#000"
android:textSize="16dp" >
</TextView>
<TextView
android:id="#+id/orderPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4sp"
android:layout_toLeftOf="#id/deleteOrder"
android:layout_toRightOf="#id/orderTitle"
android:background="#fff"
android:textColor="#000"
android:textSize="16dp" >
</TextView>
</RelativeLayout>
But it is not showing my last data in my database.
As you can see by my screen shot last data is not showing form database. Why fanta is not showing ? Always last row is showing in alertdialog from database.What is logical issue in my code i can't understand ? Most probably it is mistake of my logic but where it is i can't find . I hope i am able to explain my problem to all my well-wisher . Please help me . Thanks in advance to all
i would like to know why are u passing position -1 as param to movetoPosition method
just pass position ..
i think according to your approach last element is never being read !!
Finally i solve my issue. Thanks to all who suggest me to solve this issue.
public int getCount() {
// TODO Auto-generated method stub
Log.d(TAG, "GetCount "+starterCount);
return starterCount +1 ;
}
And
if ((position !=0)&& (position != starterCount + 1))
{
// TODO Auto-generated method stub
}

How to get the Android ID for a menu item in Android?

Is there a way to get the Android ID for a menu item? I can see getTitle() but not a getId(). I'm interested in the ID value "menu_printer_settings" rather than the title value "printer_settings" and the menu item ID (getItemId()). I need this ID to make my Monkey Talk scripts work for localized builds also.
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/menu_printer_settings"
android:title="#string/printer_settings"
/>
Solution1:
MenuItem item
String[] id = getResources().getResourceName(item.getItemId()).split("\\/");
then access id[1]
Solution2:
Use titleCondensed to match the id e.g.
<menu>
<item android:id="#+id/myid"
android:title="some menu title"
android:titleCondensed="myid"/>
...
</menu>
then
String selectedMenuIdString = (String) item.getTitleCondensed();
I prefer Solution 1 since I don't have to repeat the id name.
Hope this helps.
Regards
Steve
Try this:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_printer_settings:
//do what you want
break;
}
}
Try using getItemID() also have a look at the following if you are still having problems:
MenuItem.getItemId returns 0 instead of ItemId
Menu menu = null;
menu.findItem(R.id.item_id);
This way you access the menu item anyway in activity or fragment
Solved it by getting all the fields for the package
Map<Integer, String> idMap = new HashMap<Integer, String>();
Class<?> r;
String rClass = activity.getBaseContext().getApplicationContext().getPackageName()
+ ".R$id";
try {
r = Class.forName(rClass);
} catch (ClassNotFoundException e1) {
Log.log("Unable to load " + rClass + ": " + e1.getMessage());
return idMap;
}
for (Field f : r.getFields()) {
int val;
try {
val = f.getInt(null);
} catch (Exception e) {
throw new IllegalStateException("Unable to get value for " + f.getName() + ": "
+ e.getMessage());
}
idMap.put(val, f.getName());
}

Categories

Resources