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.
Related
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();
}
}
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I'm initialing imageview at DailyCardView.java which are called by a fragment. But it keeps showing nullPointerException. I really don't know where went wrong... Guys help me><
I tried getRootView() to get view of Fragment so i can code:iv=(ImageView)getRootView().findViewById(R.id.iv);
But it still not work.
**//Fragment**
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.home_fragment, container, false);
dailyStackLayout = (DailyStackLayout)view.findViewById(R.id.dailyStackLayout);
dailyStackLayout.setDatas(dailyFoodList);
return view;
}
**//DailyStackLayout**
public DailyStackLayout(Context context) {
this(context, null);
}
public DailyStackLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DailyStackLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void init() {
params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
scaleY = DensityUtil.dip2px(getContext(), BASESCALE_Y_VALUE);
}
public void setDatas(List<DailyFood> dailyFoodList) {
this.dailyFoodList = dailyFoodList;
if (dailyFoodList == null) {
return;
}
for (int i = index; index < i + STACK_SIZE; index++) {
dc = new DailyCardView(getContext());
dc.bind(dailyFoodList.get(index));
}
}
**//DailyCardView**
public DailyCardView(Context context) {
super(context, null);
}
public DailyCardView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public DailyCardView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
init(context);
}
public void init(Context context) {
if (!isInEditMode()) {
inflate(context, R.layout.item_daily_card, this);
iv = (ImageView)findViewById(R.id.iv);
}
}
public void bind(DailyFood dailyFood) {
if (dailyFood == null) {return;}
if (!TextUtils.isEmpty(dailyFood.getId())) {
Glide.with(**iv.getContext()**) // **NullPointerException**!
.load(Constant.Daily_URL+dailyFood.getId()+".jpg")
.into(iv);
}
I expect to load the image right but it went wrong at getContext().
dc = new DailyCardView(getContext());
This calls the DailyCardView(Context) constructor that does not call init():
public DailyCardView(Context context) {
super(context, null);
}
The init() call would init iv. And then you call bind() that assumes that iv is initialised. Bang, NPE.
Either change the super in the constructor to this to delegate to another constructor that calls init(), or just add a call to init().
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();
...
}
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
I know there are a lot of documentation about this topic, but I have a problem with the endless ListView. Each row must show a ProgressBar until the user scrolls, but it doesn't success. When the app starts, all the elements are loaded disappearing all the ProgressBar. Here is all the code.
public class MainActivity extends Activity implements EndlessListView.EndlessListener{
EndlessListView lv;
List<String> listOfElements;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout layout = new RelativeLayout(this);
lv = new EndlessListView(this);
listOfElements = fillList();
EndlessAdapter adp = new EndlessAdapter(this, listOfElements,-1);
lv.setLoadingView();
lv.setAdapter(adp);
lv.fillAdapter(listOfElements);
lv.setListener(this);
layout.addView(lv);
setContentView(layout);
}
public List<String> fillList(){
List<String> listOfElements = new ArrayList<String>();
for (int i = 0; i < 200; i++) {
listOfElements.add("Element "+i );
}
return listOfElements;
}
}
public class EndlessListView extends ListView{
Context context;
private EndlessListener listener;
private EndlessAdapter adapter;
public EndlessListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public EndlessListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EndlessListView(Context context) {
super(context);
}
public void setContext(Context context){
this.context = context;
}
public void setLoadingView() {
LinearLayout layout = new LinearLayout(super.getContext());
//this.addView(layout);
}
public void setAdapter(EndlessAdapter adapter) {
super.setAdapter(adapter);
this.adapter = adapter;
}
public EndlessListener setListener() {
return listener;
}
public void setListener(EndlessListener listener) {
this.listener = listener;
}
public static interface EndlessListener {
}
public void fillAdapter(List<String> data){
adapter.addAll(data);
adapter.notifyDataSetChanged();
}
}
And this is the critical code:
public class EndlessAdapter extends ArrayAdapter<String> {
private List<String> itemList;
private Context ctx;
private int layoutId;
public EndlessAdapter(Context ctx, List<String> itemList, int layoutId) {
super(ctx, layoutId, itemList);
this.itemList = itemList;
this.ctx = ctx;
}
#Override
public int getCount() {
return itemList.size();
}
#Override
public String getItem(int position) {
return itemList.get(position);
}
#Override
public long getItemId(int position) {
return itemList.get(position).hashCode();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv = new TextView(ctx);
ProgressBar pg = new ProgressBar(ctx);
if (convertView == null) {
tv = new TextView(ctx);
pg = new ProgressBar(ctx);
convertView = pg;
} else {
pg = (ProgressBar) convertView;
}
//tv.setText(itemList.get(position));
FakeImageLoader fake = new FakeImageLoader(tv, pg, position);
fake.execute();
System.out.println("Me estoy pintando y soy el elemento "
+ itemList.get(position));
return convertView;
}
private class FakeImageLoader extends AsyncTask<String, Void, TextView> {
private TextView tv;
private ProgressBar pg;
private int position;
public FakeImageLoader(TextView tv,
ProgressBar pg, int position) {
this.tv = tv;
this.pg = pg;
this.position = position;
}
protected void onPreExecute() {
}
protected TextView doInBackground(String... params) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return createItem(position);
}
protected void onPostExecute(TextView text) {
tv = text;
addNewData(tv, pg,position);
}
public TextView createItem(int position) {
TextView text = new TextView(ctx);
text.setText(itemList.get(position));
System.out.println(itemList.get(position));
text.setTextSize(20);
return text;
}
}
public void addNewData(TextView text, ProgressBar pg, int position) {
System.out.println("Entra");
pg.setVisibility(View.INVISIBLE);
text.setText(itemList.get(position));
}
}
Regards.