Layout problems within HorizontalScrollView - java

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();
}
}

Related

View's invalidate redraws previous texture also

I want to achieve something like this.
but instead of that, I'm getting something like this.
I'm using invalidate to redraw my custom view. But it is creating another view everytime the sides of polygon is changed. Where am I going wrong?
Here is my code.
PolygonView.Java
public class PolygonView extends View {
public float polygonRadius;
public int polygonSides;
public int polygonColor;
private Paint paint;
private Path path;
public PolygonView(Context context) {
super(context);
init(null);
}
public PolygonView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public PolygonView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public PolygonView(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs);
}
private void init(AttributeSet attrs)
{
polygonColor = ContextCompat.getColor(getContext(),R.color.polygonColor);
polygonSides = 5;
if (attrs!=null){
TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs,R.styleable.PolygonView,0,0);
polygonColor = typedArray.getColor(R.styleable.PolygonView_polygon_color,polygonColor);
polygonRadius = typedArray.getDimension(R.styleable.PolygonView_polygon_radius,polygonRadius);
polygonSides = typedArray.getInteger(R.styleable.PolygonView_polygon_sides,polygonSides);
}
paint = new Paint();
paint.setColor(polygonColor);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
path = new Path();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
double angle = 2.0*Math.PI/polygonSides;
int cx = getWidth()/2;
int cy = getHeight()/2;
path.moveTo(
(float) (cx +polygonRadius*Math.cos(0.0)),
(float) (cy +polygonRadius*Math.sin(0.0))
);
for(int i=1;i<=polygonSides;i++){
path.lineTo(
(float) (cx + polygonRadius*Math.cos(angle*i)),
(float) (cy + polygonRadius*Math.sin(angle*i))
);
}
path.close();
canvas.drawPath(path,paint);
}
}
Fragment2.Java
public class Fragment2 extends Fragment {
public Fragment2() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_polygon, container, false);
final PolygonView polygonView = v.findViewById(R.id.polygonView);
SeekBar seekBarRadius = v.findViewById(R.id.seekBarRadius);
SeekBar seekBarSides = v.findViewById(R.id.seekBarSides);
seekBarSides.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int p = progress/10;
if(p<1){
polygonView.polygonSides = 1;
}else if (p>10){
polygonView.polygonSides = 10;
}
else {
polygonView.polygonSides = p;
}
polygonView.invalidate();
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
return v;
}
}
You are always mutating your path but never reset it. Inside onDraw() method reset the path and only then apply new operations to it:
public void onDraw() {
path.reset();
...
}

Android - Custom Dialog

I'm trying to create a custom dialog where the content inside the dialog is dynamic. So I pass a view to the dialog and it will add that view to the dialog. Currently, it doesn't draw the custom view and its saying that the view has a width and height of 0.
I pass the custom view through the Application class along with a bunch of other customizations.
Here is my dialog class:
public class LoadingActivity extends Dialog
{
private LoadingActivity(Context a) {
super(a, android.R.style.Theme);
}
public static LoadingActivity show(Context context) {
LoadingActivity checkerLoader = new LoadingActivity(context);
View currentView = View.inflate(context, R.layout.loading_activity, null);
FrameLayout linearLayout = (FrameLayout) currentView.findViewById(R.id.circular_progress_bar);
RelativeLayout viewLayout = (RelativeLayout) currentView.findViewById(R.id.view_layout);
if (DataManager.getInstance().getAppConfigurations().getLoadingActivity() != null) {
View loadingView = DataManager.getInstance().getAppConfigurations().getLoadingActivity();
loadingView.setBackgroundColor(Color.RED);
loadingView.invalidate();
if(loadingView.getParent()!=null) {
((ViewGroup) loadingView.getParent()).removeView(loadingView);
}
viewLayout.addView(loadingView);
}
checkerLoader.requestWindowFeature(Window.FEATURE_NO_TITLE); //before
checkerLoader.setContentView(currentView);
checkerLoader.setCancelable(false);
checkerLoader.getWindow().getAttributes().gravity = Gravity.CENTER;
WindowManager.LayoutParams lp = checkerLoader.getWindow().getAttributes();
lp.dimAmount=0.2f;
checkerLoader.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
checkerLoader.getWindow().setAttributes(lp);
checkerLoader.show();
return checkerLoader;
}
}
Heres an example of my custom view:
public class Spinner extends LinearLayout
{
public Spinner(Context context) {
super(context);
init(context);
}
public Spinner(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public Spinner(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
View aView = View.inflate(context, R.layout.loading_activity, null);
ImageView logoImage = (ImageView) aView.findViewById(R.id.loading_image);
logoImage.setImageResource(R.drawable.loading_chicken2);
}
}
The Custom View Spinner doesn't draw anything cause the inflated layout 'R.layout.loading_activity' isn't added to a parent .
changing
View aView = View.inflate(context, R.layout.loading_activity, null);
to:
View aView = View.inflate(context, R.layout.loading_activity, this);
might help

How to add RecyclerView to a View

I have a custom view extends RelativeLayout, and I want to add a RecyclerView in it. But the recyclerView can't be shown.
How to solve it? Thanks!
The code:
LineChart.java
public class LineChart extends RelativeLayout {
RecyclerView mRecyclerView;
public LineChart(Context context) {
super(context);
init(context, null);
}
public LineChart(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public LineChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
protected void init(Context context, #Nullable AttributeSet attrs) {
setWillNotDraw(false);
initInside();
}
protected void initInside() {
View v = inflate(getContext(), R.layout.line_chart_recyclerview, null);
LineChart.LayoutParams params = new LineChart.LayoutParams(
getWidth() / 2, getHeight());
params.addRule(LineChart.ALIGN_PARENT_RIGHT);
addView(v, params);
mRecyclerView = (RecyclerView) findViewById(R.id.lineChartRecyclerView);
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");
list.add("~~~");
LineChartAdapter lineChartAdapter = new LineChartAdapter(getContext(),
list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.setAdapter(lineChartAdapter);
}
#Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
LineChartAdapter.java
public class LineChartAdapter
extends RecyclerView.Adapter<LineChartViewHolder> {
private List<String> mList;
private Context mContext;
public LineChartAdapter(Context context, List<String> list) {
this.mContext = context;
this.mList = list;
}
#Override
public LineChartViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(mContext)
.inflate(R.layout.item_line_chart, parent,
false);
return new LineChartViewHolder(itemView);
}
#Override
public void onBindViewHolder(LineChartViewHolder holder, int position) {
holder.mTextView.setText(String.valueOf(position));
}
#Override public int getItemCount() {
return mList == null ? 0 : mList.size();
}
}
LineChartViewHolder.java
public class LineChartViewHolder extends RecyclerView.ViewHolder {
protected TextView mTextView;
public LineChartViewHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(
R.id.text1024);
}
}
I think, I know the reason.
View v = inflate(getContext(), R.layout.line_chart_recyclerview, null);
LineChart.LayoutParams params = new LineChart.LayoutParams(
getWidth() / 2, getHeight());
params.addRule(LineChart.ALIGN_PARENT_RIGHT);
addView(v, params);
Here, getWidth() and getHeigth() are still 0. So your view will have (0;0) size
To fix this, I'd suggest to replace this part with
LayoutInflater.from(context).inflate(R.layout.line_chart_recyclerview, this);
Let me know, if it helps.

Custom spinner: setSelection scrolling down

I have a custom spinner
I have a Hint label that is in the last position of my array(spinner), so to display it I set selection to the last position, like this:
ArrayAdapter myAdapter = new MySpinnerAdapter(this,R.layout.spinner_item,createMyList());
myAdapter.setDropDownViewResource(spinner_item);
mySpinner.setAdapter(subCategoryAdapter);
mySpinner.setSelection(myList.size() - 1);
It's working perfectly, but when I touch on Spinner to select a item, the scroll it's "focusing" the bottom of spinner, because of my setSelection.
How can I focus on the first item of the spinner OR "scroll" to the top of it?
Thanks!
You can achieve this by extending Spinner and overriding methods that are responsible for setup and showing the list of values in the drop down:
public class CustomSpinner extends Spinner {
private boolean mToggleFlag = true;
public CustomSpinner(Context context, AttributeSet attrs, int defStyle, int mode) {
super(context, attrs, defStyle, mode);
}
public CustomSpinner(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomSpinner(Context context, int mode) {
super(context, mode);
}
public CustomSpinner(Context context) {
super(context);
}
#Override
public int getSelectedItemPosition() {
if (!mToggleFlag) {
return 0; // Gets to the first element
}
return super.getSelectedItemPosition();
}
#Override
public boolean performClick() {
mToggleFlag = false;
boolean result = super.performClick();
mToggleFlag = true;
return result;
}
}

Animate last added child in Grid View with Adapter

I have a GridView which I am constantly adding views to. When the view adds to the grid I wish for it to do an animation. However, as I have to use setAdapter() to refresh the GridView, it ends up animating all views, as they are all being re-added. Is there anyway around this?
Here is the code for my view I am adding:
public class GridImageView extends ImageView {
public GridImageView(Context context) {
super(context);
}
public GridImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GridImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ScaleAnimation anim = new ScaleAnimation(0,1,0,1);
anim.setDuration(1000);
anim.setFillAfter(true);
this.startAnimation(anim);
}
}
As always, thanks for your help
Thanks to Luksprog's suggestion, I have set a flag in my custom view which will determine if the view should animate when added to the Grid View.
public class GridImageView extends ImageView
{
private boolean _animate = false;
public GridImageView(Context context) {
super(context);
}
public GridImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GridImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onAttachedToWindow() {
if(_animate){
super.onAttachedToWindow();
ScaleAnimation anim = new ScaleAnimation(0,1,0,1);
anim.setDuration(1000);
anim.setFillAfter(true);
this.startAnimation(anim);
}
}
public void set_animate(boolean _animate) {
this._animate = _animate;
}
}
and my adapter in its GetView() function checks if it is the last in the array list, and sets the flag to true if so.
if( i == ( _gridDetailsArrayList.size() - 1 ))
holder.gridImage.set_animate(true);

Categories

Resources