i have a problem with my Android Studio version 1.2.1.1. As mentioned in title my Preview for API 21/22 doesnt keep correct view sizes, however on phone the view looks just like it should look. Is there a way to solve this?
Link: https://screencloud.net/v/nrjv
I have extended class TextView, so it supports custom fonts:
public class FontTextView extends TextView{
public FontTextView(Context context){
super(context);
}
public FontTextView(Context context, AttributeSet attrs){
super(context, attrs);
readAttributes(context, attrs);
}
public FontTextView(Context context, AttributeSet attrs, int defStyleAttr){
super(context, attrs, defStyleAttr);
readAttributes(context, attrs);
}
private void readAttributes(Context context, AttributeSet attrs){
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.FontTextView);
int fontIndex = attributes.getInt(R.styleable.FontTextView_customFont, 0);
this.setTypeface(TypefaceCreator.getTypeface(fontIndex));
attributes.recycle();
}
}
And i have class which builds these fonts while app starts:
public class TypefaceCreator {
public static final int HELVETICA_MEDIUM = 0;
public static final int HELVETICA_LIGHT = 1;
public static final int HELVETICA_ITALIC = 2;
public static final int HELVETICA_ROMAN = 3;
private static Typeface light;
private static Typeface italic;
private static Typeface roman;
private static Typeface medium;
private static TypefaceCreator creator;
private TypefaceCreator(Context context){
light = Typeface.createFromAsset(context.getAssets(),"HelveticaNeueLTPro-Lt.otf");
italic = Typeface.createFromAsset(context.getAssets(),"HelveticaNeueLTPro-It.otf");
roman = Typeface.createFromAsset(context.getAssets(),"HelveticaNeueLTPro-Roman.otf");
medium = Typeface.createFromAsset(context.getAssets(),"HelveticaNeueLTPro-Md.otf");
}
public static TypefaceCreator getInstance(Context context){
if(creator == null)
creator = new TypefaceCreator(context);
return creator;
}
public static Typeface getTypeface(int index){
switch(index) {
case HELVETICA_LIGHT:
return light;
case HELVETICA_ITALIC:
return italic;
case HELVETICA_ROMAN:
return roman;
default:
return medium;
}
}
}
Related
In my Application if the brush size is selected it changes the brush size but it also changes the size of the brush inside the canvas how to make it so that the brush size inside the canvas doesn't change.
This is my code for the EasyOne.Java - This contains contain the brushsizes:
import static com.example.artbit.display2.colorList1;
import static com.example.artbit.display2.currentbrush1;
import static com.example.artbit.display2.pathlist1;
public class EasyOne extends AppCompatActivity {
public static Path path1 = new Path();
public static Paint paintbrush1 = new Paint();
public static String brushsize1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_easy_one);
This is for the brushes
public void SmallBrush1(View view){
paintbrush1.setStrokeWidth(10f);
paintbrush1.setColor(Color.BLACK);
currentColor1(paintbrush1.getColor());
}
public static void BigBrush1(View view){
/* brushsize1 = "1";
paintbrush1.setColor(Color.BLACK);
currentColor1(paintbrush1.getColor());*/
paintbrush1.setStrokeWidth(50f);
currentColor1(paintbrush1.getColor());
}
public void Brush1(View view) {
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.selecttools);
mediaPlayer.start();
paintbrush1.setStrokeWidth(20f);
paintbrush1.setColor(Color.BLACK);
currentColor1(paintbrush1.getColor());
}
public void Clear1(View view){
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.selecttools);
mediaPlayer.start();
pathlist1.clear();
path1.reset();
colorList1.clear();
}
public static void currentColor1 (int c){
currentbrush1 = c;
path1 = new Path();
}
public static void currentsizebrush1(int c){
currentbrush1 = c;
path1 = new Path();
}
}
and this is the code for display which is the canvas this contains the pathlist and arrays for colors
import static com.example.artbit.EasyOne.paintbrush1;
import static com.example.artbit.EasyOne.path1;
import static com.example.artbit.EasyOne.brushsize1;
import android.graphics.Paint;
import android.graphics.Path;
public class display2 extends View {
public static MediaPlayer player;
public static ArrayList<Path> pathlist1 = new ArrayList<>();
public static ArrayList<Path> pathlist2 = new ArrayList<>();
public static ArrayList<Integer> brushList1 = new ArrayList<>();
public static ArrayList<Integer> colorList1 = new ArrayList<>();
public ViewGroup.LayoutParams params;
public static int currentbrush1 = Color.BLACK;
public display2(Context context) {
super(context);
init(context);
}
public display2(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public display2(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context){
paintbrush1.setAntiAlias(true);
paintbrush1.setColor(Color.BLACK);
paintbrush1.setStyle(Paint.Style.STROKE);
paintbrush1.setStrokeCap(Paint.Cap.ROUND);
paintbrush1.setStrokeJoin(Paint.Join.ROUND);
paintbrush1.setStrokeWidth(10f);
params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
path1.moveTo(x,y);
invalidate();
return true;
case MotionEvent.ACTION_MOVE:
path1.lineTo(x,y);
pathlist1.add(path1);
colorList1.add(currentbrush1);
brushList1.add(currentbrush1);
invalidate();
return true;
default:
return false;
}
}
#Override
protected void onDraw(android.graphics.Canvas canvas) {
for (int i=0; i<pathlist1.size(); i++){
paintbrush1.setColor(colorList1.get(i));
paintbrush1.setStrokeWidth(brushList1.get(i));
canvas.drawPath(pathlist1.get(i),paintbrush1);
invalidate();
}
}
}
I think I figured out the problem, the problem is in your onTouchEvent at
brushList1.add(currentbrush1);
You are adding to the ArrayList of brush's size the Color of the Path which is Black by default is -16777216 so when in draw you set the strokeWidth to a negative value it uses the Paint current value. So create a static int strokeWidth inside display2 and add to all your brush methods strokeWidth = //width number; like so
public void SmallBrush1(View view){
paintbrush1.setStrokeWidth(10f);
strokeWidth = 10; //ADD THIS
paintbrush1.setColor(Color.BLACK);
currentColor1(paintbrush1.getColor());
}
Do for all your brush methods
So change this
brushList1.add(currentbrush1);
to
brushList1.add(strokeWidth);
this should fix your problem
Hope that helps
What I'm doing to do: I'm trying to use GSON to serailize an ArrayList of custom objects. I'm making a chat app so I need to save the conversations.
I've looked at a number of different solutions of the same question and I know the answer.. GSON is trying to serialize a field object that is both in the child class and super class, but my case is a bit more difficult because I don't have access to either of those classes. Here is my stack trace.
java.lang.IllegalArgumentException: class android.widget.TextView declares multiple JSON fields named mMinWidth
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:172)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:102)
at com.google.gson.Gson.getAdapter(Gson.java:458)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:117)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:166)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:102)
at com.google.gson.Gson.getAdapter(Gson.java:458)
at com.google.gson.internal.bind.ArrayTypeAdapter$1.create(ArrayTypeAdapter.java:48)
at com.google.gson.Gson.getAdapter(Gson.java:458)
at com.google.gson.Gson.toJson(Gson.java:696)
at com.google.gson.Gson.toJson(Gson.java:683)
at com.google.gson.Gson.toJson(Gson.java:638)
at com.google.gson.Gson.toJson(Gson.java:618)
at com.widener.ConversationHistoryActivity.saveConversationList(ConversationHistoryActivity.java:93)
at com.widener.ConversationHistoryActivity$2.onClick(ConversationHistoryActivity.java:81)
at android.view.View.performClick(View.java:7870)
at android.widget.TextView.performClick(TextView.java:14951)
at android.view.View.performClickInternal(View.java:7839)
at android.view.View.access$3600(View.java:886)
at android.view.View$PerformClick.run(View.java:29315)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7762)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1047)
As you can see, it seems to be complaining about int mMinWidth in both TextView and View, it's super class. I'm completely lost and I'm not sure what to include from my code but I'll do my best. Comment if you need more information.
Code causing issue:
public void saveConversationList()
{
SharedPreferences sharedPreferences = getSharedPreferences(SharedPrefStrings.SHARED_PREFS, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
Gson gson = new Gson();
String jsonOne = gson.toJson(ConversationWrapper.conversationsHistoryList); ERROR ON THIS LINE
String jsonTwo = gson.toJson(ConversationWrapper.activeConversationIDs);
editor.putString(SharedPrefStrings.CONVERSATION_LIST, jsonOne);
editor.putString(SharedPrefStrings.CONVERSATION_LIST_IDS, jsonTwo);
editor.commit();
}
ConversationWrapper class:
public class ConversationWrapper {
public static ArrayList<Conversation> conversationsHistoryList;
}
Conversation class:
public class Conversation extends LinearLayout {
private TextView id_tag_view;
private TextView contact_name_view;
private String contact_name;
private TextView last_message_view;
private String last_message;
private ArrayList<MessageContainer> messageHistory;
public Conversation(Context context) {
super(context);
init();
}
public Conversation(Context context, String contact_name, String last_message) {
super(context);
this.contact_name = contact_name;
this.last_message = last_message;
init();
}
public Conversation(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public Conversation(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public Conversation(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init()
{
inflate(getContext(), R.layout.conversation_preview_view, this);
this.contact_name_view = (TextView) findViewById(R.id.contact_name_textview);
this.contact_name_view.setText(this.contact_name);
this.last_message_view = (TextView) findViewById(R.id.last_message_textview);
this.last_message_view.setText(this.last_message);
this.id_tag_view = (TextView) findViewById(R.id.id_tag);
this.messageHistory = new ArrayList<MessageContainer>();
}
public void setContactName(String name)
{
this.contact_name = name;
this.contact_name_view.setText(this.contact_name);
postInvalidate();
}
public void setLastMessage(String lastMessage)
{
this.last_message = lastMessage;
this.last_message_view.setText(this.last_message);
postInvalidate();
}
public void setConversationID(int id)
{
this.id_tag_view.setText(id + "");
}
public int getConversationID()
{
int id = Integer.parseInt(this.id_tag_view.getText().toString());
return id;
}
public void addMessage(MessageContainer mc)
{
this.messageHistory.add(mc);
}
public ArrayList<MessageContainer> getMessageHistory()
{
return this.messageHistory;
}
}
Any help would be appreciated. Thanks.
I have a custom control extending RadioGroup. I have a method to add custom radio button to RadioGroup (custom radio button has margins). So if i place my custom RadioGroup control inside HorizontalScrollView - it seems margins are lost. Then if soft keyboard shown - margins of radio button looks correct.
Screenshot of custom radiogroup control :
Here is a some code of my RadioGroup control
public class EDRadioGroup extends RadioGroup implements RadioGroup.OnCheckedChangeListener {
MarkerContainer mrk;
int markerContainerId;
DirectoryElement selectedElement;
public EDRadioGroup(Context context) {
super(context);
this.init(null);
}
public EDRadioGroup(Context context, AttributeSet attrs) {
super(context, attrs);
this.init(attrs);
}
private void init(#Nullable AttributeSet attributeSet) {
setOnCheckedChangeListener(this);
if (attributeSet != null) {
TypedArray a = this.getContext().getTheme().obtainStyledAttributes(attributeSet, R.styleable.ERadioGroup, 0, 0);
try {
if (a.hasValue(R.styleable.ERadioGroup_marker_container)) {
markerContainerId = a.getResourceId(R.styleable.ERadioGroup_marker_container, -1);
}
} finally {
a.recycle();
}
}
}
public void fillRadioGroup(List<DirectoryElement> items) {
if (items != null) {
for (DirectoryElement item : items) {
RadioButton rb = new YellowRadioButton(this.getContext());
rb.setText(String.format("%s%s", item.getTitle().substring(0, 1).toUpperCase(), item.getTitle().substring(1)));
rb.setTag(item);
this.addView(rb);
}
}
}
}
This is custom RadioButton code:
public class YellowRadioButton extends AppCompatRadioButton {
public YellowRadioButton(Context context) {
super(context);
this.init((AttributeSet)null);
}
public YellowRadioButton(Context context, AttributeSet attrs) {
super(context, attrs);
this.init(attrs);
}
public YellowRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.init(attrs);
}
private void init(#Nullable AttributeSet attributeSet) {
this.setBackground(ContextCompat.getDrawable(getContext(), R.drawable.radio_states_yellow));
this.setButtonDrawable(null);
this.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
this.setTextColor(ContextCompat.getColor(getContext(), R.color.dt_primary));
int padding = (int) ScreenDimensionsHelper.convertDpToPixel(10, getContext());
int minWidth = (int) ScreenDimensionsHelper.convertDpToPixel(80, getContext());
setPadding(padding, padding, padding, padding);
setMinWidth(minWidth);
setTextAlignment(TEXT_ALIGNMENT_CENTER);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
int marging = (int) ScreenDimensionsHelper.convertDpToPixel(8, getContext());
layoutParams.setMargins(marging, marging, marging, marging);
layoutParams.gravity = Gravity.CENTER;
setLayoutParams(layoutParams);
this.invalidate();
}
}
I'm new to Java and android development and I want to create this basic app, which consists of multiple CustomViews, where I could move different shapes drawn on canvas.
My idea is to have one class that handles MotionEvents and passes them to individual CustomViews.
My CustomView class:
public class CustomView extends View implements MoveDetector.OnMoveListener {
private MoveDetector mMoveDetector;
public CustomView(Context context) {
super(context);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public CustomView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs);
}
private void init(#Nullable AttributeSet set){
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#626696"));
}
#Override
public boolean onTouchEvent(MotionEvent event){
switch (event.getAction()){
case MotionEvent.ACTION_MOVE:
mMoveDetector = new MoveDetector(this);
mMoveDetector.onTouchEvent(event);
float cx = mMoveDetector.getCx();
float cy = mMoveDetector.getCy();
Toast.makeText(getContext(),"why u packin heat bro?"+Float.toString(cx)+" "+Float.toString(cy),Toast.LENGTH_SHORT).show();
Log.d("Moveee", "Move: " + Float.toString(cx)+" " + Float.toString(cy));
}
return super.onTouchEvent(event);
}
#Override
public void OnMove(MoveDetector moveDetector) {
}
}
My MoveDetector Class:
public class MoveDetector {
private float cx,cy, mCislo1,mCislo2;
public float getCx() {
return mCislo1;
}
public float getCy() {
return mCislo2;
}
private OnMoveListener mListener;
public MoveDetector(OnMoveListener listener){
mListener = listener;
}
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float y = event.getY();
mCislo1 = cXX(x);
mCislo2 = cYY(y);
if (mListener != null) {
mListener.OnMove(this);
}
break;
}
return true;}
public static interface OnMoveListener {
public void OnMove(MoveDetector moveDetector);
}
public float cXX(float x){
cx = x;
return cx;
}
public float cYY(float y){
cy = y;
return cy;
}
}
It doesn't seem to be working and I can't point why.
I searched a solution for ages and couldn't find any.
So I'd be really thankful if someone could help me out.
P.S.: Sorry, if my code is messy: I'm still learning.
I need to save a number inside an ImageView object so I can access it later in my code. That's why I created a custom class that extends ImageView:
public class SliderView extends ImageView {
private int position;
public SliderView(Context context) {
super(context);
}
public SliderView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public SliderView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setViewPosition(int pos){
this.position = pos;
}
public int getPosition(){
return position;
}
}
This is my SimpleDraweeView object in .xml :
<com.facebook.drawee.view.SimpleDraweeView
android:id="#+id/bottomslider"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
And what I am trying to achieve is this:
final SliderView mediaImage = (SliderView) convertView.findViewById(R.id.bottomslider);
When I try to run the above code, I get this error:
java.lang.ClassCastException:
com.facebook.drawee.view.SimpleDraweeView cannot be cast to
android.custom.SliderView
If I use ImageView instead of SliderView everything works fine, but I don't have the functionality that I need. Is there any workaround?
public class SliderView extends ImageView {
private int position;
public SliderView(Context context) {
super(context);
}
public SliderView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public SliderView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public SliderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setViewPosition(int pos){
this.position = pos;
}
public int getPosition(){
return position;
}
}
Try this, and let me know if this works