Android Edittext Rich Text Formatting - android

Is there any library or open source application demo that contains Rich Text Format Edittext component with WYSIWYG interface. I've heard that android-richtexteditor contained such functionality, but it's source code is no longer available.
If anyone have a link or source to the above please share it with me.

Here are two awesome libraries which helped me out. Both of them are implementation of WYSIWYG.
Android RTEditor:
https://github.com/1gravity/Android-RTEditor
RichEditor-Android:
https://github.com/wasabeef/richeditor-android
Their implementation code is also provided.

No there is no library for this but you can do that with using following classes
1.HTML
2.SPANNABLE
3.ForegroundSpan
4.BackgroundSpan
5.AbsoluteSpan
1.http://developer.android.com/reference/android/text/Html.html
using this you can embedd direct html tag with android like bold ,itlic,underlince etc
2.http://developer.android.com/reference/android/text/Spannable.html
(SpannableString ,SpannableStringBuilder, etc)
EDIT
for edit text bold,italic etc.. see some examples on below link
http://www.androidengineer.com/2010/08/easy-method-for-formatting-android.html
https://blog.stylingandroid.com/introduction-to-spans/

Here is the steps to convert an EditText into RichText
1) Create a RichTextEditor class as shown below, this example has support for bold/unbold, you can add more as needed
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.Selection;
import android.text.Spannable;
import android.text.TextWatcher;
import android.text.style.StyleSpan;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageButton;
import com.loa.learnandcheck.R;
import com.loa.learnandcheck.util.ResourceHelper;
public class RichTextEditor implements ImageButton.OnClickListener, TextWatcher {
private boolean textBold;
private ImageButton buttonBold;
private EditText editText;
private Activity parent;
private int styleStart = 0;
public RichTextEditor(Activity parent, EditText editText){
try {
this.parent = parent;
this.editText = editText;
init();
}catch (Exception e) {
e.printStackTrace();
}
}
public void init(){
try {
buttonBold = (ImageButton)parent.findViewById(R.id.text_control_text_bold);
if(buttonBold!=null) {
buttonBold.setOnClickListener(this);
}
editText.addTextChangedListener(this);
}catch (Exception e) {
e.printStackTrace();
}
}
public Activity getParent() {
return parent;
}
public void setParent(Activity parent) {
this.parent = parent;
}
public void updateBackground(boolean itemSelected, ImageButton button) {
try {
if(itemSelected) {
button.setBackgroundColor(ResourceHelper.getThemeColor(parent,R.color.colorGray, Color.GRAY));
} else {
button.setBackgroundColor(ResourceHelper.getThemeColor(parent,R.color.colorWhite, Color.WHITE));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void handleBoldButtonClick() {
try {
textBold = !textBold;
updateBackground(textBold,buttonBold);
int selectionStart = editText.getSelectionStart();
int selectionEnd = editText.getSelectionEnd();
if (selectionStart > selectionEnd){
int temp = selectionEnd;
selectionEnd = selectionStart;
selectionStart = temp;
}
if (selectionEnd > selectionStart) {
Spannable str = editText.getText();
StyleSpan[] ss = str.getSpans(selectionStart, selectionEnd, StyleSpan.class);
boolean exists = false;
for (int i = 0; i < ss.length; i++) {
if (ss[i].getStyle() == android.graphics.Typeface.BOLD){
str.removeSpan(ss[i]);
exists = true;
}
}
if (!exists){
str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void handleFormat(Editable s, int position, int format) {
try {
StyleSpan[] ss = s.getSpans(styleStart, position, StyleSpan.class);
for (int i = 0; i < ss.length; i++) {
if (ss[i].getStyle() == format){
s.removeSpan(ss[i]);
}
}
s.setSpan(new StyleSpan(format), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onClick(View view) {
try {
switch (view.getId()) {
case R.id.text_control_text_bold:
handleBoldButtonClick();
break;
//more formats to be handled as needed here...
default:
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void afterTextChanged(Editable s) {
int position = Selection.getSelectionStart(editText.getText());
//handle bold
if (textBold){
handleFormat(s, position, android.graphics.Typeface.BOLD);
}
//more formats to be handled as needed here...
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
styleStart = start;
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
//unused
}
}
2) Create the following ResourceHelper class
public class ResourceHelper {
/**
* Get a color value from a theme attribute.
* #param context used for getting the color.
* #param attribute theme attribute.
* #param defaultColor default to use.
* #return color value
*/
public static int getThemeColor(Context context, int attribute, int defaultColor) {
int themeColor = 0;
String packageName = context.getPackageName();
try {
Context packageContext = context.createPackageContext(packageName, 0);
ApplicationInfo applicationInfo =
context.getPackageManager().getApplicationInfo(packageName, 0);
packageContext.setTheme(applicationInfo.theme);
Resources.Theme theme = packageContext.getTheme();
TypedArray ta = theme.obtainStyledAttributes(new int[] {attribute});
themeColor = ta.getColor(0, defaultColor);
ta.recycle();
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return themeColor;
}
}
3) Create layout with an edittext and control buttons(ImageButtons) as shown below
<EditText
android:id="#+id/text_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:inputType="textMultiLine"
android:lines="5"
android:scrollbars="vertical"
android:background="#color/colorWhite"
android:hint="#string/text_content" />
<ImageButton
android:id="#+id/text_control_text_bold"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#color/colorWhite"
android:src="#drawable/ic_action_text_bold"/>
4) In Activity, load the edittext and create RichTextEditor instance as show below
inputText = (EditText)findViewById(R.id.text_content) ;
new RichTextEditor(this,inputText);

Related

events not showing while using a library

I am using a library for calendar called "alamkanak weekview" and I tried to add an sqLite data base where I can add and delete the events and so i did make them the delete and adding to the data base works just fine but the showing of events is all once it shows no event after i add and once it show one but repeated the time that is the size of the elements in the table , i tried to fix this but couldn't because i lack experience in android
here's the class where i add my class that adds the events from the data base
public class BasicActivity extends BaseActivity {
public db_cal db;
public int newYear;
public int newMonth;
// public int idd = 0
// ;
private List<WeekViewEvent> getEventsForMonth(int year, int month) {
List<WeekViewEvent> tempList = new ArrayList<WeekViewEvent>();
Calendar tmpen=Calendar.getInstance();
db = new db_cal(getApplicationContext());
// Populate the week view with some events.
List<WeekViewEvent> events = new ArrayList<>();
List<events> evenement = db.getAllEvenement();
WeekViewEvent event= new WeekViewEvent();
events tmp;
for(events vent : evenement) {
Log.d("taille1", evenement.size() + "");
// tmp = vent.;
//event = new WeekViewEvent(tmp.getId(), tmp.getName(),tmp.getStart(), tmp.getEnd());
event.setId(vent.getId());
event.setName(vent.getName());
event.setStartTime(vent.getStart());
event.setEndTime(vent.getEnd());
//idd=idd+1;
Log.d("nom", vent.getName() + "");
event.setColor(getResources().getColor(randcol()));
events.add(event);
}
for (WeekViewEvent weekViewEvent : events) {
if ((weekViewEvent.getStartTime().get(Calendar.MONTH))+1 == month && weekViewEvent.getStartTime().get(Calendar.YEAR) ==
year) {
tempList.add(weekViewEvent);
}
}
return tempList;
}
public List<? extends WeekViewEvent> onMonthChange(int newYear, int newMonth) {
int month = newMonth;
return getEventsForMonth(newYear,month);// I tried to use newMonth-1 directly here but it dosen't work i don't know why but it doesn't matter
}
/* #Override
public List<? extends WeekViewEvent> onMonthChange(int newYear, int newMonth) {
this.newYear = newYear;
this.newMonth = newMonth;
/* Calendar tmpdb=Calendar.getInstance();
Calendar tmpen=Calendar.getInstance();
db = new db_cal(getApplicationContext());
// Populate the week view with some events.
List<WeekViewEvent> events = new ArrayList<>();
List<events> evenement = db.getAllEvenement();
WeekViewEvent event= new WeekViewEvent();
events tmp;
for(int i=0;i<evenement.size();i++) {
Log.d("taille1",evenement.size()+"");
tmp=evenement.get(i);
//event = new WeekViewEvent(tmp.getId(), tmp.getName(),tmp.getStart(), tmp.getEnd());
event.setId(i);
event.setName(tmp.getName());
event.setStartTime(tmp.getStart());
event.setEndTime(tmp.getEnd());
//idd=idd+1;
Log.d("nom",tmp.getName()+"");
event.setColor(getResources().getColor(randcol()));
events.add(event);
}
return events;
}*/
int randcol(){
int[]val={
R.color.event_color_01,
R.color.event_color_02,
R.color.event_color_03,
R.color.event_color_04
};
int rand=new Random().nextInt(val.length);
return val[rand];
}
/*#Override
public void onEmptyViewLongPress(Calendar time) {
}*/
}
and this is the class with the events called
package com.example.calendar;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.RectF;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import com.alamkanak.weekview.DateTimeInterpreter;
import com.alamkanak.weekview.MonthLoader;
import com.alamkanak.weekview.WeekView;
import com.alamkanak.weekview.WeekViewEvent;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
public abstract class BaseActivity extends AppCompatActivity implements WeekView.EventClickListener, MonthLoader.MonthChangeListener, WeekView.EventLongPressListener, WeekView.EmptyViewLongPressListener {
private static final int TYPE_DAY_VIEW = 1;
private static final int TYPE_THREE_DAY_VIEW = 2;
private static final int TYPE_WEEK_VIEW = 3;
private int mWeekViewType = TYPE_THREE_DAY_VIEW;
private WeekView mWeekView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
// Get a reference for the week view in the layout.
mWeekView = (WeekView) findViewById(R.id.weekView);
// Show a toast message about the touched event.
mWeekView.setOnEventClickListener(this);
// The week view has infinite scrolling horizontally. We have to provide the events of a
// month every time the month changes on the week view.
mWeekView.setMonthChangeListener(this);
// Set long press listener for events.
mWeekView.setEventLongPressListener(this);
// Set long press listener for empty view
mWeekView.setEmptyViewLongPressListener(this);
// Set up a date time interpreter to interpret how the date and time will be formatted in
// the week view. This is optional.
setupDateTimeInterpreter(false);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
setupDateTimeInterpreter(id == R.id.action_week_view);
if(id == R.id.action_today)
{
mWeekView.goToToday();
return true;
}
if(id== R.id.action_day_view) {
if (mWeekViewType != TYPE_DAY_VIEW) {
item.setChecked(!item.isChecked());
mWeekViewType = TYPE_DAY_VIEW;
mWeekView.setNumberOfVisibleDays(1);
// Lets change some dimensions to best fit the view.
mWeekView.setColumnGap((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics()));
mWeekView.setTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics()));
mWeekView.setEventTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics()));
}
return true;
}
else if(id== R.id.action_three_day_view) {
if (mWeekViewType != TYPE_THREE_DAY_VIEW) {
item.setChecked(!item.isChecked());
mWeekViewType = TYPE_THREE_DAY_VIEW;
mWeekView.setNumberOfVisibleDays(3);
// Lets change some dimensions to best fit the view.
mWeekView.setColumnGap((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics()));
mWeekView.setTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics()));
mWeekView.setEventTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics()));
}
return true;
}
else if(id == R.id.action_week_view)
{
if (mWeekViewType != TYPE_WEEK_VIEW) {
item.setChecked(!item.isChecked());
mWeekViewType = TYPE_WEEK_VIEW;
mWeekView.setNumberOfVisibleDays(7);
// Lets change some dimensions to best fit the view.
mWeekView.setColumnGap((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics()));
mWeekView.setTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10, getResources().getDisplayMetrics()));
mWeekView.setEventTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10, getResources().getDisplayMetrics()));
}
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Set up a date time interpreter which will show short date values when in week view and long
* date values otherwise.
*
* #param shortDate True if the date values should be short.
*/
private void setupDateTimeInterpreter(final boolean shortDate) {
mWeekView.setDateTimeInterpreter(new DateTimeInterpreter() {
#Override
public String interpretDate(Calendar date) {
SimpleDateFormat weekdayNameFormat = new SimpleDateFormat("EEE", Locale.FRANCE);
String weekday = weekdayNameFormat.format(date.getTime());
SimpleDateFormat format = new SimpleDateFormat(" d/M/Y", Locale.FRANCE);
// All android api level do not have a standard way of getting the first letter of
// the week day name. Hence we get the first char programmatically.
// Details: http://stackoverflow.com/questions/16959502/get-one-letter-abbreviation-of-week-day-of-a-date-in-java#answer-16959657
if (shortDate)
weekday = String.valueOf(weekday.charAt(0));
return weekday.toUpperCase() + format.format(date.getTime());
}
#Override
public String interpretTime(int hour) {
return ""+hour ;
}
});
}
#Override
public void onEmptyViewLongPress(Calendar time) {
Toast.makeText(this, "Empty view long pressed: " + getEventTitle(time), Toast.LENGTH_SHORT).show();
startActivity(new Intent(getApplicationContext(),addEvent.class));
finish();
}
protected String getEventTitle(Calendar time) {
return String.format("l'evenement de %02d:%02d %s/%d", time.get(Calendar.HOUR_OF_DAY), time.get(Calendar.MINUTE), time.get(Calendar.MONTH) + 1, time.get(Calendar.DAY_OF_MONTH));
}
#Override
public void onEventClick(WeekViewEvent event, RectF eventRect) {
Toast.makeText(this, "l'evenement : " + event.getName(), Toast.LENGTH_SHORT).show();
}
#Override
public void onEventLongPress(final WeekViewEvent event, RectF eventRect) {
//Toast.makeText(this, "Long pressed event: " + event.getName(), Toast.LENGTH_SHORT).show();
AlertDialog.Builder supprimer = new AlertDialog.Builder(BaseActivity.this);
supprimer.setMessage("voulez vous supprimer cet evenement ?")
.setCancelable(false)
.setPositiveButton("confirmer", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
db_cal db = new db_cal(getApplicationContext());
Calendar b=event.getStartTime();
Calendar e = event.getEndTime();
String name = event.getName();
db.supprimer(b,e,name);
}
}).setNegativeButton("annuler", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog alert = supprimer.create();
alert.setTitle("supprimer evenement");
alert.show();
}
public WeekView getWeekView() {
return mWeekView;
}
}
i would like to show these events correctly if anyone can help

onClick listener not responding

I was making a project for my class. It's like whac a mole game. I have 9 imageView's in this. As you click on them, they will change to a predefined image of empty hole, if not, the handler will change it back to normal and you will loose a life. But for one picture, if it appears and you click on it, you loose a life. Right now I have fixed the image to be the later one. If I click on them very fast, the textView which shows lives, never gets updated to game over, and tasks continue, but if I click slowly, it gets updated to game over. I tried debugging and found out that when I have clicked on them very quickly, the code never goes to onClick listener.
Here is the code:
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import Hole;
public class MainActivity extends Activity {
final Activity mainActivityObject = this;
final int MIN_TYPES_OF_MOLES = 0;
final int TYPES_OF_MOLES_INC_INT = 1;
final int MAX_MOLE_LIFE_TIME = 3000;
final int LIFE_TIME_DECREASE_INT = 150;
final int MAX_MOLE_APPEARANCE_INT = 1000;
final int APPEARANCE_TIME_DECREASE_INT = 60;
final int SPEED_UP_TIME_INT = 20000;
final int BOMB_MOLE_ID = 3;
final int MIN_DIFFICULTY_LEVEL = 1;
private Toast toast;
final Handler handler = new Handler();
Runnable moleAliveChecker;
Runnable speedUp;
TextView lives;
TextView tView;
//private ImageView[] holeImage = new ImageView[9];
private Hole[] hole = new Hole[9];
private int totalScore = 0;
private int active = 0;
private int numberOfLives = 3;
private int appearanceInterval = MAX_MOLE_APPEARANCE_INT;
private int moleLifeTime = MAX_MOLE_LIFE_TIME;
private int typesOfMoles = MIN_TYPES_OF_MOLES;
private int speedUpTime = SPEED_UP_TIME_INT;
private int difficultyLevel = MIN_DIFFICULTY_LEVEL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);// hide the title
setContentView(R.layout.activity_main);
tView = (TextView) findViewById(R.id.time_left);
lives = (TextView) findViewById(R.id.lives_left);
toast = Toast.makeText(getApplicationContext(), "", Toast.LENGTH_LONG);
//set images and listener for each hole, ends game if lives < 1
for(int counter=0;counter<9;counter++)
{
int resID=getResources().getIdentifier("hole"+(counter+1),"id",getPackageName());
hole[counter] = new Hole((ImageView)findViewById(resID), this);
final int i=counter;//inside the onClickListener, index number has to be final
hole[counter].getImage().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ImageView image = hole[i].getImage();
switch ((Integer) image.getTag()) {
case R.drawable.hole:
break;
default:
if (numberOfLives < 1) {
handler.removeCallbacks(speedUp);
lives.setText("GAME OVER!!");
}
else if (hole[i].getMole().ishit()) {
changeScoreAndLives(hole[i], i);
}
break;
}
}
});
}
// gives a time delay of 3 seconds before beginning the game and updates text view
// tView every 1 second and when time approaches 0, it starts the game
final Runnable r = new Runnable() {
int t = 3;
public void run() {
if (t > 0) {
tView.setText("Game begins in : " + t-- + " Seconds");
handler.postDelayed(this, 1000);
}
else if (t == 0)
{
t--;
tView.setText("Begin!!");
handler.postDelayed(this, 300);
}
else
{
if (numberOfLives >= 1) {
playGame();
handler.postDelayed(this, appearanceInterval);
}
}
}
};
handler.postDelayed(r, 1000);
// speeds up the game after a set interval (20 seconds)
speedUp = new Runnable() {
public void run() {
appearanceInterval -= APPEARANCE_TIME_DECREASE_INT;
moleLifeTime -= LIFE_TIME_DECREASE_INT;
typesOfMoles += TYPES_OF_MOLES_INC_INT;
difficultyLevel++;
if (difficultyLevel < 6 && numberOfLives >= 1) {
handler.postDelayed(this, speedUpTime);
}
toast.setText("Difficulty Level increased");
toast.show();
}
};
handler.postDelayed(speedUp, speedUpTime);
}
// end of onCreate
// not been used yet
private void resetOneStep()
{
if (difficultyLevel > MIN_DIFFICULTY_LEVEL) {
appearanceInterval += MAX_MOLE_APPEARANCE_INT;
moleLifeTime += MAX_MOLE_LIFE_TIME;
typesOfMoles -= MIN_TYPES_OF_MOLES;
difficultyLevel--;
handler.postDelayed(speedUp, speedUpTime);
}
}
// not related to the current problem as currently not being used
public void bombMoleCredit()
{
for (int count = 0; count < hole.length; count++)
if (hole[count].getMole() !=null) {
totalScore += hole[count].getMole().getPoints();
handler.removeCallbacksAndMessages(count);
hole[count].setImage(null, mainActivityObject);
}
tView.setText("Total Score: " + totalScore);
active = 0;
}
// called by onclick listener if lives > 0 to change lives, score, and image
public void changeScoreAndLives(Hole hole, int number)
{
totalScore = totalScore + hole.getMole().getPoints();
if (hole.getMole().getPoints() < 0) {
numberOfLives--;
lives.setText("Lives Left: " + numberOfLives);
}
if (hole.getMole().getID() == BOMB_MOLE_ID) {
bombMoleCredit();
return;
}
handler.removeCallbacksAndMessages(number);
hole.setImage(null, mainActivityObject);
active--;
tView.setText("Total Score: " + totalScore);
}
// called by runnable after a set interval
public void playGame()
{
if (active == 9)
return;
final int holeNumber = (int) (Math.random() * hole.length);
if (hole[holeNumber].getMole() == null && numberOfLives >= 1) {
hole[holeNumber].setMoleFromRange(4, 4, this);
active++;
// checks if the hole has been clicked or not after a few seconds, if not, player
// looses a life
moleAliveChecker = new Runnable() {
Hole holeToBeChecked = hole[holeNumber];
public void run() {
if (holeToBeChecked.getMole() != null && numberOfLives >= 1) {
if(holeToBeChecked.getMole().getID() == 4) {
holeToBeChecked.setImage(null, mainActivityObject);
active--;
return;
}
holeToBeChecked.setImage(null, mainActivityObject);
numberOfLives--;
active--;
TextView lives = (TextView) findViewById(R.id.lives_left);
lives.setText("Lives Left: " + numberOfLives);
toast.setText("OOPS!! you lost a life. Game Reset");
toast.show();
//resetOneStep();
}
}
};
handler.sendMessageDelayed(getPostMessage(moleAliveChecker, holeNumber), moleLifeTime);
}
else
playGame(); // in case the random number choses the image which has the mole
}
// to pass object as a token in postDelayed in handler, to cancel the callbacks
private final Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain(handler, r);
m.obj = token;
return m;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
All the other classes are working fine except for this one.
Other important classes:
Mole.java
import android.app.Activity;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import java.io.InputStream;
public class Mole
{
public static final int DEFAULT_ID = 0; // regular mole ID
// private methods
private JSONParser parser;
private JSONObject mole;
private int ID, timesToBeHit, timesHit, points;
private String name;
private JSONArray moles;
private boolean active;
public Mole(int ID, Activity map)
{
try {
// initialize and read json and convert each object to jsonArray
parser = new JSONParser();
// tries to set the value set by user. If fails, sets the default value
if (!setMoleByID(ID, map))
setMoleByID(DEFAULT_ID, map);
}
catch (Exception e)
{
e.printStackTrace();
}
}
// helper for constructor
private boolean setMoleByID(int ID, Activity map) throws Exception
{
InputStream is = map.getAssets().open("moles.json");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
String json = new String(buffer, "UTF-8");
moles = (JSONArray)parser.parse(json);
// go through each object in array moles
for ( Object obj : moles)
{
// convert oobject to jsonObject
mole = (JSONObject) obj;
// if id matches it leaves the mole to be that jsonObject and exits
// the loop
if ((long)mole.get("ID") == ID)
break;
}
if ((long)mole.get("ID") != ID)
return false;
// initialize private data so that we don't have to rely on json
// anymore after this step
this.ID = (int)(long)mole.get("ID");
name = (String)mole.get("name");
timesToBeHit = (int)(long)mole.get("timesToBeHit");
timesHit = 0;
points = (int)(long)mole.get("points");
return true;
}
// get methods
public int getID() { return ID; }
public String getName() { return name; }
public int getTimesHit() { return timesHit; }
public int getTimesToBeHit() { return timesToBeHit; }
public int getPoints() { return points; }
public boolean ishit()
{
if (timesHit >= timesToBeHit - 1)
return true;
timesHit++;
return false;
}
public static int getTotalTypesOfMoles() throws Exception
{
return 5;
}
}
Hole.java
import android.app.Activity;
import android.widget.ImageView;
import com.example.phoenix.whac_a_mole03.R;
// NOT completed yet
// HOLE Class -----------------------------------------------------------------
public class Hole
{
private Mole mole;
private boolean active; // if true then mole is present
private ImageView image;
public Hole(ImageView view,final Activity map)
{
mole = null;
image = view;
setImage(mole, map);
}
// sets mole from a random value
public boolean setMoleFromRange(int minMoleID,
int maxMoleID, Activity map)
{
try {
int typesOfMoles = Mole.getTotalTypesOfMoles() - 1;
// checks for validity of data here
if (!(minMoleID >= 0 & minMoleID <= typesOfMoles))
return false;
if (!(maxMoleID >= 0 & maxMoleID <= typesOfMoles))
return false;
if (minMoleID > maxMoleID)
return false;
// chooses the random value between a range
int moleID =
(int) (Math.random() * (maxMoleID + 1 - minMoleID)) + minMoleID;
mole = new Mole(moleID, map);
setImage(mole, map);
return true;
}
catch (Exception e)
{
e.printStackTrace();
}
return false;
}
private void clear()
{
mole = null;
}
public void setImage(Mole mole, Activity map)
{
if (mole == null) {
image.setImageResource(R.drawable.hole);
image.setTag(R.drawable.hole);
clear();
return;
}
int imageID = map.getResources().getIdentifier("mole" + mole.getID() , "drawable", map.getPackageName());
image.setImageResource(imageID);
image.setTag(imageID);
this.mole = mole;
}
public boolean hit(Activity map)
{
if (!mole.ishit())
return false;
setImage(mole, map);
return true;
}
// get methods
public Mole getMole() { return mole; }
public ImageView getImage() { return image;}
// REST STUFF TO BE ADDED HERE-------------
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView
android:id="#+id/time_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/lives_left"
android:layout_alignParentRight="true"
android:text="Lives Left: 3"
android:textAlignment="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<GridLayout
android:columnCount="3"
android:rowCount="3"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/hole1"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole2"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole3"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole4"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole5"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole6"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole7"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole8"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole9"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
</GridLayout>
<GridLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/life1"/>
<ImageView
android:id="#+id/life2"/>
<ImageView
android:id="#+id/life3"/>
</GridLayout>
</RelativeLayout>
Any picture can be used as long as it is named mole4.png and when there is no mmole then hole.png
Thanks a lot. I will appreciate your help

How to make EditText read and copy only but not editable

I want to make my edit box read only but not editable.
User should able to copy from my Edit box but it should not be editable ny user.
please let me know how to do this.
The command text.setTextIsSelectable(true) requires API 11. For those using lower API's use the following XML:
android:inputType="none"
android:textIsSelectable="true"
This will make your editText selectable but not editable.
The easiest way to do this is to add this code:
textInput.setInputType(InputType.TYPE_NULL);
textInput.setTextIsSelectable(true);
textInput.setKeyListener(null);
Create a TextView as has been indicated by the other answer, instead of an EditText. Then override the Activity's context menu in your Activity class as below:
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
menu.add(0, v.getId(), 0, "Copy");
//cast the received View to TextView so that you can get its text
TextView yourTextView = (TextView) v;
//place your TextView's text in the clipboard
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(yourTextView.getText());
}
Then simply call registerForContextMenu(yourTextView); in onCreate().
You can overwrite the key listener, so you can do anything except editing
final EditText edittext = (EditText) findViewById(R.id.edittext);
edittext.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
return true;
}
});
Use android:editable="false" property for the EditText in your layout view file.
i'm using this class
import android.content.Context;
import android.text.InputFilter;
import android.text.Spanned;
import android.util.AttributeSet;
import android.widget.EditText;
/*
*
* To make EditText read and copy only but not editable
* using
* sendReadOnlyCallback(callback);
*
*/
public class MyEditText extends EditText {
private InputFilter[] originalFilters = null;
private boolean internalChange = false;
private InputFilter[] myInputFilters = null;
private static ReadonlyCallback sDummyCallback = new ReadonlyCallback() {
#Override
public boolean isReadOnly() {
return false;
}
};
private ReadonlyCallback callback = sDummyCallback;
public MyEditText(Context context) {
super(context);
}
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public interface ReadonlyCallback {
public boolean isReadOnly();
}
public void setReadonlyCallback(ReadonlyCallback cb) {
if (cb == null)
callback = sDummyCallback;
else
callback = cb;
}
public void setFilters(InputFilter[] filters) {
// duplicated from TexView
originalFilters = new InputFilter[filters.length];
System.arraycopy(filters, 0, originalFilters, 0, filters.length);
// funny No. 1 : have to re instantiate `callback`
// otherwise got `NullPointerExcection` when called from `filter`
callback = sDummyCallback;
myInputFilters = new InputFilter[] { new InputFilter() {
// funny No. 2:
// have to make refs to `originalfilters`
// otherwise got `NullPointerExcection` when called from `filter`
InputFilter[] flts = originalFilters;
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (!internalChange && callback.isReadOnly())
return dest.subSequence(dstart, dend);
int filtercount = flts.length;
if (filtercount == 0)
return null;
// duplicated from InputFilter.AllCaps
for (int i = 0; i < filtercount; i++) {
CharSequence repl = flts[i].filter(source, start, end, dest, start, end);
if (repl != null) {
source = repl;
start = 0;
end = repl.length();
}
if (i == filtercount)
return repl;
}
return null;
}
} };
super.setFilters(myInputFilters);
}
#Override
public InputFilter[] getFilters() {
if (myInputFilters == null)
return super.getFilters();
return originalFilters;
}
#Override
public synchronized void setText(CharSequence text, BufferType type) {
internalChange = true;
super.setText(text, type);
internalChange = false;
}
}
Why not this?
final EditText edittext = (EditText) findViewById(R.id.edittext);
edittext.setEnabled(false);

Show log messages on screen for Android application

Is it possible to display the log messages (which I print using android.util.Log) on screen in an Android application?
Is there any other better method to just output lines on the screen?
Something like System.out.println?
Like others have suggested, you can use log cat. If you are using the emulator or debugging a device, you can use adb logcat to view the messages. In Eclipse debug perspective, there is a window that will do that for you.
Another way, without a debugger attached, is to use the CatLog - Logcat Reader application.
Yes zero4
what you are attempting to do is dropping 'logcat' comand on android shell & getting command output as output stream.This link will help you.
I use "android.widget.Toast.makeText(Context context, CharSequence text, int duration)" to do something like what you are asking. Seems like the easiest way to get some quick messages on the screen and make it go away automatically (based on the last parameter).
:-)
Well, there is a solution to log anything you want on screen using this lib. It didn't worked for me, so I develop my own solution you can find an example of it here. It's really simple, just add a class OnScreenLog to your project
package br.com.ideiageni.onscreenlogSample;
import android.app.Activity;
import android.graphics.Color;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* Created by ariel on 07/07/2016.
*/
public class OnScreenLog {
private static int timeoutTime = 1000;
private static TextView tvLog;
private static int logCount = 0;
private static int logCountMax = 30;
private static String[] logs = new String[logCountMax];
private static int cntClicks = 0;
private static boolean visibility = false;
private static Activity activity;
private int maxClicks = 5;
public OnScreenLog(){}
public OnScreenLog(Activity activity, int ViewID){
OnScreenLog.activity = activity;
tvLog = new TextView(activity.getApplicationContext());
maintainLog("Log is working");
tvLog.setLayoutParams(new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
tvLog.setTextColor(Color.BLACK);
tvLog.setBackgroundColor(Color.LTGRAY);
tvLog.setAlpha((float) 0.4);
View v = null;
LinearLayout linearLayout;
RelativeLayout relativeLayout;
try {
linearLayout = (LinearLayout) activity.findViewById(ViewID);
} catch (ClassCastException e) {linearLayout = null;};
try {
relativeLayout = (RelativeLayout) activity.findViewById(ViewID);
} catch (ClassCastException e) {relativeLayout = null;};
if(linearLayout != null) {
linearLayout.addView(tvLog);
v = linearLayout;
} else if(relativeLayout != null) {
relativeLayout.addView(tvLog);
v = relativeLayout;
}
if(v != null) {
v.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
cntClicks++;
timerHandler.removeCallbacks(rTimeout);
timerHandler.postDelayed(rTimeout, timeoutTime);
if (cntClicks > maxClicks-1) {
setLogVisible(!visibility);
timerHandler.removeCallbacks(rTimeout);
cntClicks = 0;
}
break;
}
return false;
}
});
}
}
public void log (String text){
String logText = text;
maintainLog(logText);
}
public void log (int text){
String logText = String.valueOf(text);
maintainLog(logText);
}
public void log (int[] text){
StringBuilder builder = new StringBuilder();
for (int i : text) {
builder.append(i);
builder.append("-");
}
String logText = builder.toString();
maintainLog(logText);
}
public void log (byte[] text){
StringBuilder builder = new StringBuilder();
for (int i : text) {
builder.append(i);
builder.append("-");
}
String logText = builder.toString();
maintainLog(logText);
}
private void maintainLog(String newText){
String logText = "";
if(logCount<logCountMax) logCount++;
for(int i=logCount-1; i>0; i--){
logs[i] = logs[i-1];
}
logs[0] = newText;
for(int i=0; i<logCount; i++){
if(i<logCount-1) logText+=logs[i]+System.getProperty("line.separator");
else logText+=logs[i];
}
tvLog.setText(logText);
}
public void clearLog(){
tvLog.setText("");
}
public void setLogVisible(boolean visibility){
if(visibility) tvLog.setVisibility(View.VISIBLE);
else tvLog.setVisibility(View.INVISIBLE);
OnScreenLog.visibility = visibility;
}
public static int getLogCountMax() {
return logCountMax;
}
public static void setLogCountMax(int logCountMax) {
OnScreenLog.logCountMax = logCountMax;
logs = new String[logCountMax];
}
public int getMaxClicks() {
return maxClicks;
}
public void setMaxClicks(int maxClicks) {
this.maxClicks = maxClicks;
}
Handler timerHandler = new Handler();
Runnable rTimeout = new Runnable() {
#Override
public void run() {
cntClicks = 0;
}
};
}
then, for instance:
public class Activity1 extends AppCompatActivity {
private OnScreenLog log;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_1);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
log = new OnScreenLog(this, R.id.content_1);
log.log("Started log on Activity 1");
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), Activity2.class);
startActivity(intent);
log.log("Starting Activity 2");
Snackbar.make(view, "Starting Activity 2", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
Where R.id.content_1 is the name of the main LinearLayout or RelativeLayout of your activity.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/content_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="br.com.ideiageni.onscreenlogSample.Activity1"
tools:showIn="#layout/activity_1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity 1!" />
</RelativeLayout>
Neither solutions print the current log messages, so you'll need to tell it to log to screen the same informations you log today on your current log.
Work not finished yet but can be used for anyone in need. Missing some directions on how to use. Suggestions are welcome.

Ellipsize only a section in a TextView

I was wondering if it is possible to abbreviate only a portion of a string in a TextView. What I would like to do is something like this:
Element with short title (X)
Element with a very lo...(X)
The title should be ellipsized, but the X must be always visible. In my case, is not possible to use more than one TextView. Do you think there is a simple way of doing this?
Thanks!
I really needed a clean solution for a project so after searching around and not finding any solutions I felt I liked, I took some time to write this up.
Here is an implementation of a TextView with enhanced ellipsis control. The way it works is by using Android's Spanned interface. It defines an enum you can use to tag the specific section of text you'd like to be ellipsized if needed.
Limitations:
Does not support ellipsis at MIDDLE. This should be easy to add if it's really needed (I didn't).
This class will always render the text onto one line, as it only supports a single line of text. Others are welcome to extend it if that's needed (but it's a far harder problem).
Here's a sample of the usage:
FooActivity.java
class FooActivity extends Activity {
/**
* You can do this however you'd like, this example uses this simple
* helper function to create a text span tagged for ellipsizing
*/
CharSequence ellipsizeText(String text) {
SpannableString s = new SpannableString(text);
s.setSpan(TrimmedTextView.EllipsizeRange.ELLIPSIS_AT_END, 0, s.length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
return s;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.foo_layout);
TextView textView = (TextView) findViewById(R.id.textView4);
SpannableStringBuilder text = new SpannableStringBuilder();
text.append(ellipsizeText("This is a long string of text which has important information "));
text.append("AT THE END");
textView.setText(text);
}
}
res/layouts/foo_layout.xml
<com.example.text.TrimmedTextView
android:id="#+id/textView4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"/>
That's it
Here's an example of the result:
The Implementation
package com.example.text;
import android.content.Context;
import android.text.Editable;
import android.text.Layout;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextUtils.TruncateAt;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;
public class TrimmedTextView extends TextView {
public static enum EllipsizeRange {
ELLIPSIS_AT_START, ELLIPSIS_AT_END;
}
private CharSequence originalText;
private SpannableStringBuilder builder = new SpannableStringBuilder();
/**
* This allows the cached value of the original unmodified text to be
* invalidated whenever set externally.
*/
private final TextWatcher textCacheInvalidator = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
originalText = null;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
};
public TrimmedTextView(Context context) {
this(context, null, 0);
}
public TrimmedTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TrimmedTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
addTextChangedListener(textCacheInvalidator);
Log.v("TEXT", "Set!");
}
/**
* Make sure we return the original unmodified text value if it's been
* custom-ellipsized by us.
*/
public CharSequence getText() {
if (originalText == null) {
return super.getText();
}
return originalText;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Layout layout = getLayout();
CharSequence text = layout.getText();
if (text instanceof Spanned) {
Spanned spanned = (Spanned) text;
int ellipsisStart;
int ellipsisEnd;
TruncateAt where = null;
ellipsisStart = spanned.getSpanStart(EllipsizeRange.ELLIPSIS_AT_START);
if (ellipsisStart >= 0) {
where = TruncateAt.START;
ellipsisEnd = spanned.getSpanEnd(EllipsizeRange.ELLIPSIS_AT_START);
} else {
ellipsisStart = spanned.getSpanStart(EllipsizeRange.ELLIPSIS_AT_END);
if (ellipsisStart >= 0) {
where = TruncateAt.END;
ellipsisEnd = spanned.getSpanEnd(EllipsizeRange.ELLIPSIS_AT_END);
} else {
// No EllipsisRange spans in this text
return;
}
}
Log.v("TEXT", "ellipsisStart: " + ellipsisStart);
Log.v("TEXT", "ellipsisEnd: " + ellipsisEnd);
Log.v("TEXT", "where: " + where);
builder.clear();
builder.append(text, 0, ellipsisStart).append(text, ellipsisEnd, text.length());
float consumed = Layout.getDesiredWidth(builder, layout.getPaint());
CharSequence ellipsisText = text.subSequence(ellipsisStart, ellipsisEnd);
CharSequence ellipsizedText = TextUtils.ellipsize(ellipsisText, layout.getPaint(),
layout.getWidth() - consumed, where);
if (ellipsizedText.length() < ellipsisText.length()) {
builder.clear();
builder.append(text, 0, ellipsisStart).append(ellipsizedText)
.append(text, ellipsisEnd, text.length());
setText(builder);
originalText = text;
requestLayout();
invalidate();
}
}
}
}
You can try using something like this:
myTextView.setEllipsize(TextUtils.TruncateAt.MIDDLE);
It might not give you exactly what you want though, it may do something like this:
Element wi...title (X)
Reference Info
TruncateAt
setEllipsize

Categories

Resources