Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bars not showing bar chart #1742

Closed
sjuvvalapalem opened this issue Oct 29, 2016 · 27 comments
Closed

Bars not showing bar chart #1742

sjuvvalapalem opened this issue Oct 29, 2016 · 27 comments

Comments

@sjuvvalapalem
Copy link

Hi,

Ever since upgrading to 3.0, i am having trouble with the bars not showing in the bar chart.

One bar shows when the data has only one point. If i add more than one point then the bars donot show.
This is happening only when the xaxis has dates. if i change the data from dates to say integer then it works fine.
Please see the attached screenshots.

A sample of the data would be similar to this
{
"09/04/2012":"245",
"02/05/2013":"227",
"04/07/2013':"234",
"07/08/2015":"244",
"10/11/2016":"2254"
}

Thanks,
Bob

1

As seen below i dont see the bars at all? what seems to be causing this?
2

@sjuvvalapalem
Copy link
Author

Any one has a solution for this?
It seems strange that the bars are missing in 3.0. Looks like i am either missing a call or setting something, it would be super helpful if there is a solution for this.

Thanks,
Bob

@liuxuan30
Copy link
Member

How do you set it up? Chart 3.0 has redesigned x axis, so lots of things changed. If you don't update your code, it might be missing. For now, please check ChartsDemo for different bar chart demos.

@sjuvvalapalem
Copy link
Author

I will run the Demo charts again and see if i can reproduce the issue, but i believe the issue is similar to the other issue #1716 opened.

Let me get back to you once i make some changes and running the Charts Demo.

It seems certain x-values are causing issues.

Thanks,
Bob

@avitus
Copy link

avitus commented Oct 31, 2016

I'm having the same problem. My X-axis correctly shows the date in format YYYY-MM-DD but the bars are invisible.

@sjuvvalapalem
Copy link
Author

@liuxuan30 ,
here is what i basically tried ... I made some changes to the ChartsDemo in 3.0 and it is doing exactly the same thing...

I made the following changes. instead of X value being a double, i am adding the datetime since 1970 which is the double value for the dates.
changed the xaxis formatter to a dd/MM .

Also attaching the code for the BarChartViewController.m that way you could check it.

See the screenshot below.
simulator screen shot nov 1 2016 12 22 47 am

BarChartViewController.m.zip

Either i am missing something very simple or this is a bug.

Thanks,
Bob

@sakuraehikaru
Copy link

Hi, I am not sure why this issue is closed, but like everyone who has described the symptoms here and in #1716, I am experiencing the same bug in our project. In short, the X-axis can't seem to handle large values such as time intervals, and it somehow messes up the rendering of the chart.

@liuxuan30
Copy link
Member

liuxuan30 commented Nov 2, 2016

@sjuvvalapalem the original ChartsDemo works fine right? I don't know the context about your changes. In Chart 3.0, x values are always double. If you changed anything, make sure you change all related field. You screenshot is just missing the bars, so I think you could check drawDataSets in bar chart renderer for more details. It's easier to debug on your side.

@sjuvvalapalem
Copy link
Author

sjuvvalapalem commented Nov 2, 2016

BarChartViewController.m.zip
@liuxuan30 i have attached the changes i made in my reply earlier.
All i did was instead of double just added the Nstimeinterval for some dates and for some reason its not showing the bars.

I think this could be a bug. Please look at the attached zip document, you could easily figure out the changes i made and that should make sense.
Looking at the same issue for the other people, i suspect this could be a bug.
Any help on this is greatly appreciated as my project is being halted for this instead of getting pushed to the appstore.

Any solution to this would greatly help.

Thanks,
Bob

@sjuvvalapalem
Copy link
Author

@liuxuan30 could you please make this issue Open? so that this gets more traction just like the others mentioned.

Thanks,
Bob

@liuxuan30 liuxuan30 reopened this Nov 3, 2016
@liuxuan30
Copy link
Member

liuxuan30 commented Nov 3, 2016

I m sorry that I'm busy with my work recently, so I can't take a look at this very quickly. Will try
NSTimeInterval is double I remember, so it should not impact..

@sjuvvalapalem
Copy link
Author

@liuxuan30 yes, it is a double. With the formatter, the dates show up correctly. the values above the bars show correctly.

Everything is working but the bars are not showing.

If you are busy, Is there any one else who could look into this issue/bug?

Thanks,
Bob

@liuxuan30
Copy link
Member

liuxuan30 commented Nov 3, 2016

alright, I did a quick check.
The x axis range is

(lldb) po max - min
34041601.0

When rendering, barRect width is too small:

▿ (30.7373051480045, 132.310035326087, 8.28906013339292e-06, 257.842777173913)
  ▿ origin : (30.7373051480045, 132.310035326087)
    - x : 30.7373051480045
    - y : 132.310035326087
  ▿ size : (8.28906013339292e-06, 257.842777173913)
    - width : 8.28906013339292e-06 //  <-- you won't see it
    - height : 257.842777173913

So you don't see it.
The reason is, the x val is too big, so in prepareBuffer(),

let barWidthHalf = barData.barWidth / 2.0 // barWidth is 0.9

then

let left = CGFloat(x - barWidthHalf)
let right = CGFloat(x + barWidthHalf)
barRect.size.width = right - left

it's trivial.

@danielgindi seems like we need to handlebarWidth to cope with big values? Or it's by design.

The x range is very large, but just a few bars, however we use a hard coded number to present the bar width, which causes trouble. I tried to "normalize" the barWidth, buggy.

The temporary workaround is to uses bigger day units, not seconds for x values. Or you just turn it into 1,2,3,4,.. and let the formatter to format. In your data, your x vals are over one year, even in days, it's 365 bars and the bar would be thin too.

Another way is to change barWidth that fit your value range. However, there is no clear shot how to find the right number yet.

@frederic-adda
Copy link

frederic-adda commented Jan 18, 2017

Hi,
I have the exact same problem, but the issue seems to be closed without giving any solution ...
If I use a line chart, the chart is drawing correctly but if I chose vertical bar chart, no bar appears.
To me, that is NOT an enhancement, it's a bug.

Thanks

@liuxuan30 liuxuan30 added the bug label Feb 13, 2017
@Pikacz
Copy link

Pikacz commented Jul 18, 2017

setting BarChartData.barWidth to huge value (~10 000) solved problem for me

@brittanygraft
Copy link

I got around this issue by setting a border
chartDataSet.barBorderColor = UIColor.blue
chartDataSet.barBorderWidth = 30
Hope that helps

@mannyveloso
Copy link

Setting barBorderWidth seems to fix the issue.

@sjuvvalapalem
Copy link
Author

Any solution for this issue? Setting barBorderWidth seems to work but it doesnt really work the right way because if there is only one or 2 data points the lines are too thin (assuming you set it the barBorderWidth to 1). If set to a higher number then all the bars are joined and mingled together and doesnt look good.

Any work on this is greatly appreciated.

@Vaianaa
Copy link

Vaianaa commented Nov 17, 2018

Work Like A Charm !

bars not displaying

My Analysis:
This is a bug ... Date in long data type has value 1542039314621, it means 12 November 2018 After formatted using SimpleDateFormat. But x Axis takes its long value first, that causing trouble. My solution is xHelper, instead input big value, xHelper doing index long data type implicitly using counter counter++, beside xValue hold big long value. and this code work like a charm

this is wrong code:

String[] month = new String[] {"Jan", "Feb", "Mar", "Aprl"};     
xAxis.setValueFormatter(new MyXAxisValueFormatter(month)); 

This is wrong code:

 xAxis.setValueFormatter(new IAxisValueFormatter() {
         @override
         public String getFormattedValue (float value, AxisBase axis){
              Date dates = new Date((long) value); //take your long value from BarEntry 
              SimpleDateFormat sdf = new SimpleDateFormat("dd/MM");
              return  sdf.format(dates);
              }
}

This is incorrect code:

for (int i = 0; i < xValues.length; i++)
Date date = new Date(xValues[i]);

this is wrong code :

List<Date> dates = new ArrayList<Date>();
for (int i = 0; i< xHelper.length; i++)
dates.add(new Date(xValues[i]));

this code work like a charm:

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM"); // as you seen on the picture 
String[] xDates = new String[xHelper.length];
for (int m = 0; m < xHelper.length; m++) 
      xDates[m] = sdf.format(new Date(xValues[m]));

List<String> myDateList = new ArrayList<String>();
for (int n = 0; n < xHelper.length; n++)
      myDateList.add(xDates[n]);

//convert your ArrayList into array
String[] month = (String[]) myDateList.toArray(new String[xHelper.length]);

xAxis.setValueFormatter(new YourXAxisValueFormatter(month));

This is my full code and tell everything about xValue and xHelper.

public class MyDatabaseHelper {
long xValue
int xHelper, yValues;

//empty constructor
public MyDatabaseHelper(){
}

//constructor
public MyDatabaseHelper(long xValue, int yValues, int xHelper){
         this.xValue = xValue;
         this.yValue = yValue;
         this.xHelper = xHelper;
}

//Method
public long getxValue() {return xValues;}

public int getyValue() {return yValues;}

public int getxHelper() {return xHelper;}
}

next make this class and thanks to Phillip Jahoda

 public class MyXAxisValueFormatter implements IXAxisValueFormatter {
          private String[] mValues;`
          
          //constructor with array parameter
         public MyAxisValueFormatter(String[] values) {
                this.mValues = values;
          }

         @override
         public String getFormattedValue(float value, AxisBase axis) {
              return mValues[(int) value];
         }
}

finally make MainActivity class:

public class MainActivity extends AppCompatActivity {

EditText yInput;
Button buttonInsert;
FirebaseDatabase firebaseDatabase;
DatabaseReference reference;
BarChart barChart;
//this is xHelper as counter for indexing x values
int counter = 0;

@override
protected void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        yInput = (EditText) findViewById(R.id.editText);
        insertButton = (Button) findViewById(R.id.buttonInsert);
        firebaseDatabase = FirebaseDatabase.getInstance();
        reference = firebaseDatabase.getReference("ChartTable");
        insert();
  }
     public void insert() {
           buttonInsert.setOnClickListener(new View.OnClickListener() {
                   @override
                    public void onClick (View v)
                    String id = reference.push().getKey();
                    long x = new Date().getTime();  //this is big value
                    int y = yInput.getText().toString();
                    
                    // when you click button this counter increase
                    //note: using this counter will make your app being crash on 5 step Granularity
                    //my granularity is setGranularity(5);
                    //this is my problem and i don't know why. so, i have to make the counter start from zero
                    //like this                
                    counter++
                    int c = counter - 1;

                    // input value into class
                    MyDatabaseHelper db = new MyDatabaseHelper(x, y, c);
                    //input method into Firebase Database
                    reference.child(id).setValue(db);
           });
     }

    @override
    protected void onStart {
    super.onStart();
                   
                   reference.addValueEventListener(new ValueEventListener() {
                            @override
                            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                             
                                    int count = (int) dataSnapshot.getChildrenCount();
                                    long[] xValues = new long[count];
                                    int[] yValues = new int[count];
                                    int[] xHelper = new int[count];
                                   
                                    int index = 0;
                                    for (DataSnapshot myDataSnapshot : dataSnapshot.getChildren()){
                                    MyDatabaseHelper db = myDataSnapshot.getValue(MyDatabaseHelper.class);
                                    xValues[index] = db.getxValue();
                                    yValues[index] = db.getyValue();
                                    xHelper[index] = db.getxHelper();
                                    index++
                                   }
                                   
                                   ArrayList<BarEntry> barEntry = new ArrayList<BarEntry>();
                                   for (int i = 0; i < xHelper.length; i++)
                                         barEntry.add(new BarEntry(xHelper[i], yValues[i]));
              
                                   BarDataSet set1 = new BarDataSet(barEntry, "Project Progress");
                                   set1.setColors(ColorTemplate.VORDIPLOM_COLORS);
                                   set1.setDrawValues(false);                              

                                   ArrayList<IBarDataSet> dataSets =  new ArrayList<>();
                                   dataSets.add(set1);
 
                                   BarData data = new BarData(dataSets);

                                   XAxis xAxis = barChart.getXAxis();
                                   xAxis.setGranularity(5f);
                                   xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
                                   
                                   // input xValues[] into Date using List
                                   SimpleDateFormat sdf = new SimpleDateFormat("dd/MM");
                                   String[] xDates = new String[count];
                                   for (int m =0; m < xValues.length; m++)
                                         xDates[m] = sdf.format(new Date(xValues[m]));

                                  List<String> xDatesList = new ArrayList<String>();
                                  for (int n = 0; n < xDates.length; n++)
                                         xDatesList.add(xDates[n]);
       
                                  // you cannot insert xDatesList directly into setValueFormatter
                                  //so convert ArrayList into array
                                  String[] month = (String[]) xDatesList.toArray(new String[count]);
                                  
                                 //finally
                                 xAxis.setValueFormatter(new MyXAxisValueFormatter(month));
                                //done
                                barChart.getAxisRight().setEnabled(false);
                                barChart.setDragEnabled(true);
                                barChart.setScaleEnabled(true);
                                barChart.setPinchZoom(true);
                                barChart.setDoubleTapToZoomEnabled(false);
                                barChart.setDrawGridBackground(false);
                                barChart.setDragEnabled(true);

                                barChart.setData(data);
                                barChart.invalidate();


                             }
                             @override
                             public void onCancelled(@NonNull DatabaseError databaseError){
                            }
                   });
    }
} 

Everything is done. And this is my Description:

I don't use this code:

String[] month = new String[] {"Jan", "Feb", "Mar", "Aprl"};     
xAxis.setValueFormatter(new MyXAxisValueFormatter(month)); 

because i need dynamic input and don't want write "jan", "feb" and so forth. my solution:
String[] month = (String[]) myDateList.toArray(new String[xHelper.length]);

myDateList.toArray allow you to take ArrayList and insert it into array.

And i don't use this code because -->

xAxis.setValueFormatter(new IXAxisValueFormatter {

         @override
         public String getFormattedValue(float value, AxisBase axis) {
              Date dates = new Date((long) value)
              SimpleDateFormat sdf = new SimpleDateFormat("dd/MM");
              return sdf.format(dates);
         }
}

because that value taken from x Axis that cause your Bars dissapear. my solution is xHelper like this:

ArrayList<BarEntry> barEntry = new ArrayList<BarEntry>();
for (int i=0; i<xHelper.length; i++)
    barEntry.add(new BarEnry(xHelper[i], yValues[i]));

the point is, xHelper must contain small value for indexing Date

And this is the secret:
you don't input Date using this --> String[] month = new String[]{...}; but myDateList

String[] month = (String[]) myDateList.toArray(new String[xHelper.length]);
xAxis.setValueFormatter(new YourXAxisValueFormatter(month));

@nikhilroy782
Copy link

@sjuvvalapalem @avitus did you find any solution for this.

@siltrifork
Copy link

It's been 2 years now since this bug was reported, and there's still not a fix?

@liuxuan30
Copy link
Member

can you file a PR to fix this? I originally marked it added this to To do in 4.0 Release

@ChristianVinterly
Copy link

Not sure if this helps anyone, but I had the same problem and solved it by setting my bars to correct size relative to the range of the x-axis:

let data = BarChartData(dataSets: [dataSet])

let dataSetRange = dataSet.xMax - dataSet.xMin
let availableSpacePerBar = dataSetRange / Double(dataSet.entryCount)
data.barWidth = availableSpacePerBar * 0.8 // 80% of available space

chartView.data = data

@piyush-priyadarshi-dev
Copy link

piyush-priyadarshi-dev commented May 16, 2020

setting BarChartData.barWidth to huge value (~10 000) solved problem for me

This one works better then #1742 (comment) when u have some missing values in between your data range, ie. non continuous and periodic data source.

If you have missing values in between,
Following the comment #1742 (comment)
Screenshot 2020-05-16 at 12 52 11 PM

setting BarChartData.barWidth to huge value (~10 000) looks like
Screenshot 2020-05-16 at 12 52 40 PM

But both works great when u have all sufficient continuous values
IMG_81DD4290AE1B-1

@superandrew
Copy link

superandrew commented May 19, 2020

I just lost 3 hours for this, so keeping an eye on it. Ended by using indexes.

@marshtupa
Copy link

Hi there! I Find new solution to solve this problem.

The main point is to round timeIntervalSince1970 to amount of days.
Because I don't need more than a day precision

extension TimeInterval {
    private static let secondsInDay: TimeInterval = 60 * 60 * 24
    
    func getDays() -> Double {
        let val = (self / TimeInterval.secondsInDay)
        return val.rounded(.towardZero)
    }
    
    func daysToSeconds() -> Double {
        return self * TimeInterval.secondsInDay
    }
}

How to create ChartDataEntry

ChartDataEntry(x: transaction.date!.timeIntervalSince1970.getDays(), y: someVal)

And formatter look like this


public class DateValueFormatter: NSObject, AxisValueFormatter {
    private let dateFormatter = DateFormatter()
    
    override init() {
        super.init()
        dateFormatter.dateFormat = "dd.MM"
    }
    
    public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        let str = dateFormatter.string(from: Date(timeIntervalSince1970: value.daysToSeconds()))
        return str
    }
}

Simulator Screen Shot - iPhone 11 - 2021-10-17 at 08 46 07

@dattatrayParthenon
Copy link

dattatrayParthenon commented Nov 29, 2021

I'm still facing issue, I had tried all solutions mentioned in different comments but they don't work. setting bar width fixing issue of showing bar but selecting bar does not work.

@RRCummins
Copy link

Not sure if this helps anyone, but I had the same problem and solved it by setting my bars to correct size relative to the range of the x-axis:

let data = BarChartData(dataSets: [dataSet])

let dataSetRange = dataSet.xMax - dataSet.xMin
let availableSpacePerBar = dataSetRange / Double(dataSet.entryCount)
data.barWidth = availableSpacePerBar * 0.8 // 80% of available space

chartView.data = data

This workaround works for me. This is still a bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests