I followed the whole procedure from the Developer page, except that I used androidx new tools in order to support gif insertion - doc here: https://developer.android.com/guide/topics/text/image-keyboard
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.EditText;
import androidx.core.os.BuildCompat;
import androidx.core.view.inputmethod.EditorInfoCompat;
import androidx.core.view.inputmethod.InputConnectionCompat;
import androidx.core.view.inputmethod.InputContentInfoCompat;
public class CoolEditText extends EditText {
public CoolEditText(Context context) {
super(context);
}
public CoolEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CoolEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
final InputConnection ic = super.onCreateInputConnection(editorInfo);
EditorInfoCompat.setContentMimeTypes(editorInfo,
new String[]{"image/gif"});
Log.e("CVE","onCreateInputConnection");
final InputConnectionCompat.OnCommitContentListener callback =
new InputConnectionCompat.OnCommitContentListener() {
#Override
public boolean onCommitContent(InputContentInfoCompat inputContentInfo,
int flags, Bundle opts) {
Log.e("CVE","onCommitContent");
// read and display inputContentInfo asynchronously
if (BuildCompat.isAtLeastNMR1() && (flags &
InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
try {
inputContentInfo.requestPermission();
} catch (Exception e) {
return false; // return false if failed
}
}
return true; // return true if succeeded
}
};
return InputConnectionCompat.createWrapper(ic, editorInfo, callback);
}
}
Unfortunately, I keep getting "this app doesn't support gif insertion message" while I try to use GBoard
Any idea what might be wrong? The code is quite simple and I don't see where the mistake could be...
Note: as you can see in code, I logged "onCreateInputConnection" and that is fired, but "onCommitContent" is never called
I don't know if you found your response, but I had the same problem.
I success by creating the new CoolEditText programmatically.
I hope it will help someone.
#Robert :
coolInputText = new CoolInputText(context);
this.addView(coolInputText);
Related
I have created a real time firebase database whose one of the child is "availability". While populating all the firebase data in listview, I want the text from the child to be coloured in Green if the string value of "availability" is "yes" else in Red.
Is it possible? If yes, please show me the way.
(I have populate the child in various activities, it will be really helpful if I could state the condition universally)
Thank You.
yes possible use below class
You have to create custom Textview like this
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.widget.TextView;
public class CustomTextViewTest extends android.support.v7.widget.AppCompatTextView {
public CustomTextViewTest(Context context) {
super(context);
}
public CustomTextViewTest(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public CustomTextViewTest(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
// here set color according to text
if (text.toString().contains("availability")) {
this.setTextColor(Your Color);
} else {
this.setTextColor(Your Color);
}
}
}
I want to make a re-usable Listview control from listView in which the columns can be controlled , Say I want to load 3 column list view and sometimes 2 and sometimes 4 .
How can I Control the columns and rows pro-grammatically for a list view.Depending upon my json values I will display the list.
Also I want to make some column editable also .This also needs to be controlled by code level
This is my code which I started :
import android.content.Context;
import android.graphics.Color;
import android.graphics.PorterDuff;
import org.json.JSONArray;
import org.json.JSONObject;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class LayoutAdvancedList extends ListView {
private String m_name;
private int m_editMask = 0;
private int m_EditedRowIndex = 0;
private int m_EditedFieldIndex = 0;
public String getName() {
return m_name;
}
public void setName(String name) {
this.m_name = name;
}
public void setMaxLength(final int maxLength) {
if (maxLength > 0) {
// super.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)});
} else {
// super.setFilters(new InputFilter[]{});
}
}
public void setReadOnly(final boolean readOnly) {
super.setFocusable(!readOnly);
super.setFocusableInTouchMode(!readOnly);
super.setClickable(!readOnly);
super.setLongClickable(!readOnly);
// super.setCursorVisible(!readOnly);
}
public LayoutAdvancedList(Context context) {
super(context);
LayoutInitialize(context);
}
public LayoutAdvancedList(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInitialize(context);
}
public LayoutAdvancedList(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
LayoutInitialize(context);
}
#Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
if (enabled) {
this.getBackground().setColorFilter(null);
} else {
this.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
}
}
If you have the choice, you should use a RecyclerView for this with a GridLayoutManager so you can choose the number of columns on the fly:
recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
Here's an example of how to make a RecyclerView
Presumably each item in your ListView is defined by child views arranged to make up 2-4 columns in each row, depending on your requirement. Simply control the presence/absence of each column programmatically using view.setVisibility(View.GONE), view.setVisibility(View.VISIBLE) or view.setVisibility(View.INVISIBLE)
Recently I've been trying to create a CustomView.
I am following the tutorial and did as directed but when i tried to run the code my CustomView was not displayed on my android screen.
My code for attrs.xml is:-
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TimeView">
<attr name="text" format="string"/>
<attr name="setColor" format="boolean"/>
</declare-styleable>
</resources>
Here is the code for my CustomView i.e TimeView.java:-
package com.example.custom;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.widget.TextView;
public class TimeView
extends TextView{
public String titleText;
public boolean color;
public TimeView(Context context) {
super(context);
setTimeView();
// TODO Auto-generated constructor stub
}
public TimeView(Context c,AttributeSet as)
{
super(c,as);
TypedArray ty=c.obtainStyledAttributes(as,R.styleable.TimeView);
int count=ty.getIndexCount();
try{
for(int i=0;i<count;i++)
{
int attr=ty.getIndex(i);
if(attr==R.styleable.TimeView_text)
{
titleText=ty.getString(attr);
}
else if(attr==R.styleable.TimeView_setColor)
{
color=ty.getBoolean(attr, false);
decorate();
}
}
}
finally
{
ty.recycle();
}
}
public TimeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setTimeView();
}
public void setTimeView()
{
SimpleDateFormat sdf=new SimpleDateFormat("hh.mm aa");
String time=sdf.format(Calendar.getInstance().getTime());
if(this.titleText!=null)
{
setText(this.titleText+" "+time);
}
else
setText(time);
}
public void decorate()
{
if(this.color==true)
{
setShadowLayer(4, 2, 2, Color.rgb(250, 00, 250));
setBackgroundColor(Color.CYAN);
}
else{
setBackgroundColor(Color.RED);
}
}
}
and lastly here is the code for my activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.example.custom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.custom.MainActivity" >
<com.example.custom.TimeView
android:id="#+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
custom:text="My View"
custom:setColor="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</LinearLayout>
I am getting this result:-
I don't know where i am doing mistake.
Please help me!
Thank you in advance.
Just overwrite your code with my code it's working. You just make mistake while retrieving attributes.
Don't forget to add your package name at first line
import java.text.SimpleDateFormat;
import java.util.Calendar;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.widget.TextView;
public class TimeView
extends TextView {
public String titleText;
public boolean color;
public TimeView(Context context) {
super(context);
setTimeView(context, null);
}
public TimeView(Context c, AttributeSet as) {
super(c, as);
setTimeView(c, as);
}
public TimeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setTimeView(context, attrs);
}
public void setTimeView(Context c, AttributeSet attrs) {
TypedArray a;
if (attrs != null) {
a = c.getTheme().obtainStyledAttributes(
attrs,
R.styleable.BLProgress,
0, 0);
} else {
throw new IllegalArgumentException("Must have to pass the attributes");
}
try {
titleText = a.getString(R.styleable.TimeView_text);
color = a.getBoolean(R.styleable.TimeView_setColor, false);
} finally {
a.recycle();
}
SimpleDateFormat sdf = new SimpleDateFormat("hh.mm aa");
String time = sdf.format(Calendar.getInstance().getTime());
if (this.titleText != null) {
setText(this.titleText + " " + time);
} else
setText(time);
decorate();
}
public void decorate() {
if (color) {
setShadowLayer(4, 2, 2, Color.rgb(250, 00, 250));
setBackgroundColor(Color.CYAN);
} else {
setBackgroundColor(Color.RED);
}
}
}
here is the screen shot ..
i'm trying to work with building my own Preference classes, and having a bit of trouble. it looks like the way of saving data to a preference is via the "persist" group of methods within the Preference class. however, in my preference, i open a color picker dialog, and i need to save the preference from within the dialog's colorChanged override. whenever i run the app and try to change the color preference, i get:
06-05 10:21:46.396: ERROR/AndroidRuntime(516): FATAL EXCEPTION: main
java.lang.IllegalAccessError: tried to access method android.preference.Preference.persistInt:(IIII)V from class android.preference.ColorSelectionPreference$1
at android.preference.ColorSelectionPreference$1.colorChanged(ColorSelectionPreference.java:55)
at android.apis.graphics.ColorPickerDialog.onClick(ColorPickerDialog.java:168)
(UPDATE: 6/5/12 12:20) i tried using callChangeListener to force the onPreferenceChangeListener to trigger, but it crashes with an identical error. without callChangeListener, the preference data is (probably) saved, but the onPreferenceChangeListener doesn't get triggered:
06-05 12:20:23.691: ERROR/AndroidRuntime(2834): FATAL EXCEPTION: main
java.lang.IllegalAccessError: tried to access method android.preference.ColorSelectionPreference.callChangeListener:(IIII)V from class android.preference.ColorSelectionPreference$1
at android.preference.ColorSelectionPreference$1.colorChanged(ColorSelectionPreference.java:52)
at android.apis.graphics.ColorPickerDialog.onClick(ColorPickerDialog.java:168)
here's the actual class:
package android.preference;
import android.apis.graphics.ColorPickerDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.util.AttributeSet;
public class ColorSelectionPreference extends Preference {
private Context mContext;
private int mColor;
public ColorSelectionPreference(Context context) {
super(context);
mContext = context;
}
public ColorSelectionPreference(Context context, AttributeSet attr) {
super(context, attr);
mContext = context;
}
public int getColor() {
return mColor;
}
public void setColor(int color) {
mColor = color;
}
#Override
public void onClick() {
//get original preference
//set ColorPickerDialog to original preference color or default color
ColorPickerDialog dialog = new ColorPickerDialog(mContext, new ColorPickerDialog.OnColorChangedListener() {
public void colorChanged(int a, int r, int g, int b) {
int selectedColor = Color.argb(a,r,g,b);
setColor(selectedColor);
/*** crashes on callChangeListener ***/
//SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
//SharedPreferences.Editor edit = prefs.edit();
//edit.putInt(getKey(), selectedColor);
//edit.commit();
//callChangeListener(selectedColor);
/*** the offending code, error refers to this line ***/
persistInt(selectedColor);
/*** tried this as well by request on IRC ***/
//ColorSelectionPreference.this.persistInt(selectedColor);
}
}, mColor);
dialog.show();
}
}
this is a hacky workaround that uses a Handler to call back to the main class from the inner class. it isn't pretty, but it works.
package android.preference;
import android.apis.graphics.ColorPickerDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
public class ColorSelectionPreference extends Preference {
private Context mContext;
private int mColor;
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if(msg.getData().containsKey("color")) {
int color = msg.getData().getInt("color");
setColor(color);
}
}
};
public ColorSelectionPreference(Context context) {
super(context);
mContext = context;
}
public ColorSelectionPreference(Context context, AttributeSet attr) {
super(context, attr);
mContext = context;
}
public int getColor() {
return mColor;
}
public void setColor(int color) {
mColor = color;
persistInt(new Integer(color));
}
#Override
public void onClick() {
//get original preference
//set ColorPickerDialog to original preference color or default color
ColorPickerDialog dialog = new ColorPickerDialog(mContext, new ColorPickerDialog.OnColorChangedListener() {
public void colorChanged(int a, int r, int g, int b) {
int selectedColor = Color.argb(a,r,g,b);
Bundle bundle = new Bundle();
bundle.putInt("color", selectedColor);
Message msg = new Message();
msg.setData(bundle);
mHandler.sendMessage(msg);
//setColor(selectedColor);
/*** tried this, but the onPreferenceChangedListener never gets triggered, so this won't work ***/
//SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
//SharedPreferences.Editor edit = prefs.edit();
//edit.putInt(getKey(), selectedColor);
//edit.commit();
//callChangeListener(selectedColor);
/*** the offending code, error refers to this line ***/
//container.
/*** tried this as well by request on IRC ***/
//ColorSelectionPreference.this.persistInt(selectedColor);
}
}, mColor);
dialog.show();
}
}
I just encountered this problem myself. I do not pretend to understand it, but this seems like an easier fix:
// ...why is this necessary? what is special about Preference.persistInt?
#Override protected boolean persistInt(int value)
{
return super.persistInt(value);
}
Inspired by how-do-i-display-the-current-value-of-an-android-preference-in-the-preference-summary i created my own EditTextPreference that shows its current value in the PreferenceScreen.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen android:key="preferences" xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="First Category"
android:key="first_category">
<de.k3b.widgets.EditTextPreferenceWithSummary
android:key="test"
android:title="Test Message"
android:dialogTitle="Test Message"
android:dialogMessage="Provide a message"
android:defaultValue="Default welcome message" />
</PreferenceCategory>
</PreferenceScreen>
The implementation looks like this
package de.k3b.widgets;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.*;
import android.util.AttributeSet;
import android.util.Log;
public class EditTextPreferenceWithSummary extends EditTextPreference {
private final static String TAG = EditTextPreferenceWithSummary.class.getName();
public EditTextPreferenceWithSummary(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public EditTextPreferenceWithSummary(Context context) {
super(context);
init();
}
private void init() {
Log.e(TAG, "init");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this.getContext());
String currentText = test prefs.getString("minTrashholdInSecs", this.getText());
// where do i get the current value of the underlaying EditTextPreference ??
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
this.setSummary(this.getText());
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Log.w(TAG, "display score changed to "+newValue);
preference.setSummary(newValue.toString()); // getSummary());
return true;
}
});
}
}
When the PreferenceScreen is first shown there is no current value displayed.
My problem: Where do i get the current value that the EditTextPreference represents?
getText() does not get the value as i expected.
After changing the preferencevalue this value is shown in the summary field as expected.
Im am using android 2.2
Try to add the following code to your EditTextPreferenceWithSummary class:
#Override
protected View onCreateView(ViewGroup parent) {
this.setSummary(this.getText());
return super.onCreateView(parent);
}
As for me, it works.
I think the problem was that you were trying to change the UI state out of UI thread (in fact in the constructor).
Here is a more complete example, that includes when the value updates, without having to install preference listeners.
import android.content.Context;
import android.preference.EditTextPreference;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
public class EditTextPreferenceWithValueSummary extends EditTextPreference{
public EditTextPreferenceWithValueSummary(Context context) {
super(context);
}
public EditTextPreferenceWithValueSummary(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected View onCreateView(ViewGroup parent) {
this.setSummary(this.getText());
return super.onCreateView(parent);
}
#Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
this.setSummary(getText());
}
}
}
And in your xml/settings.xml:
<your.package.views.EditTextPreferenceWithValueSummary
android:key="some_preference_key"
android:title="Some Title" />